mirror of
https://github.com/wassname/talk.git
synced 2026-07-19 11:28:50 +08:00
[CORL-406] Tenant Locale Selection (#2450)
* feat: added preload config * feat: support changing locale * fix: name case * fix: removed unused code * feat: added translations for default reactions * fix: do not translate icon * fix: shorter i18n keys
This commit is contained in:
@@ -13,7 +13,6 @@ async function main() {
|
||||
const ManagedCoralContextProvider = await createManaged({
|
||||
initLocalState,
|
||||
localesData,
|
||||
userLocales: navigator.languages,
|
||||
});
|
||||
|
||||
const Index: FunctionComponent = () => (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FormApi, FormState } from "final-form";
|
||||
import React from "react";
|
||||
|
||||
import { CoralContext, withContext } from "coral-framework/lib/bootstrap";
|
||||
import { SubmitHookHandler } from "coral-framework/lib/form";
|
||||
import { MutationProp, withMutation } from "coral-framework/lib/relay";
|
||||
|
||||
@@ -9,6 +10,7 @@ import NavigationWarningContainer from "./NavigationWarningContainer";
|
||||
import UpdateSettingsMutation from "./UpdateSettingsMutation";
|
||||
|
||||
interface Props {
|
||||
changeLocale: CoralContext["changeLocale"];
|
||||
updateSettings: MutationProp<typeof UpdateSettingsMutation>;
|
||||
children: React.ReactElement;
|
||||
}
|
||||
@@ -27,6 +29,10 @@ class ConfigureRoute extends React.Component<Props, State> {
|
||||
form: FormApi
|
||||
) => {
|
||||
await this.props.updateSettings({ settings: data });
|
||||
const localeFieldState = form.getFieldState("locale");
|
||||
if (localeFieldState && localeFieldState.dirty) {
|
||||
await this.props.changeLocale(data.locale);
|
||||
}
|
||||
form.initialize(data);
|
||||
};
|
||||
|
||||
@@ -52,6 +58,8 @@ class ConfigureRoute extends React.Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
const enhanced = withMutation(UpdateSettingsMutation)(ConfigureRoute);
|
||||
const enhanced = withContext(({ changeLocale }) => ({ changeLocale }))(
|
||||
withMutation(UpdateSettingsMutation)(ConfigureRoute)
|
||||
);
|
||||
|
||||
export default enhanced;
|
||||
|
||||
@@ -8,6 +8,7 @@ import ClosingCommentStreamsConfigContainer from "./ClosingCommentStreamsConfigC
|
||||
import CommentEditingConfigContainer from "./CommentEditingConfigContainer";
|
||||
import CommentLengthConfigContainer from "./CommentLengthConfigContainer";
|
||||
import GuidelinesConfigContainer from "./GuidelinesConfigContainer";
|
||||
import LocaleConfigContainer from "./LocaleConfigContainer";
|
||||
import ReactionConfigContainer from "./ReactionConfigContainer";
|
||||
import SitewideCommentingConfigContainer from "./SitewideCommentingConfigContainer";
|
||||
|
||||
@@ -19,7 +20,8 @@ interface Props {
|
||||
PropTypesOf<typeof ClosedStreamMessageConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof ReactionConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof ClosingCommentStreamsConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof SitewideCommentingConfigContainer>["settings"];
|
||||
PropTypesOf<typeof SitewideCommentingConfigContainer>["settings"] &
|
||||
PropTypesOf<typeof LocaleConfigContainer>["settings"];
|
||||
onInitValues: (values: any) => void;
|
||||
}
|
||||
|
||||
@@ -29,6 +31,11 @@ const General: FunctionComponent<Props> = ({
|
||||
onInitValues,
|
||||
}) => (
|
||||
<HorizontalGutter size="double" data-testid="configure-generalContainer">
|
||||
<LocaleConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
onInitValues={onInitValues}
|
||||
/>
|
||||
<SitewideCommentingConfigContainer
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
|
||||
@@ -45,6 +45,7 @@ class GeneralConfigContainer extends React.Component<Props> {
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
settings: graphql`
|
||||
fragment GeneralConfigContainer_settings on Settings {
|
||||
...LocaleConfigContainer_settings
|
||||
...GuidelinesConfigContainer_settings
|
||||
...CommentLengthConfigContainer_settings
|
||||
...CommentEditingConfigContainer_settings
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { useMemo } from "react";
|
||||
import { Field } from "react-final-form";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { LocaleConfigContainer_settings } from "coral-admin/__generated__/LocaleConfigContainer_settings.graphql";
|
||||
import { LocaleField } from "coral-framework/components";
|
||||
import { withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { required } from "coral-framework/lib/validation";
|
||||
import { FormField, HorizontalGutter, Typography } from "coral-ui/components";
|
||||
|
||||
import Header from "../../Header";
|
||||
import ValidationMessage from "../../ValidationMessage";
|
||||
|
||||
interface Props {
|
||||
settings: LocaleConfigContainer_settings;
|
||||
onInitValues: (values: LocaleConfigContainer_settings) => void;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
const LocaleConfigContainer: React.FunctionComponent<Props> = props => {
|
||||
useMemo(() => props.onInitValues(props.settings), [props.onInitValues]);
|
||||
return (
|
||||
<FormField>
|
||||
<HorizontalGutter size="full">
|
||||
<Localized id="configure-general-locale-language">
|
||||
<Header container={<label htmlFor="configure-locale-locale" />}>
|
||||
Language
|
||||
</Header>
|
||||
</Localized>
|
||||
<Localized
|
||||
id="configure-general-locale-chooseLanguage"
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography variant="detail">
|
||||
Choose the language for your Coral community.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Field name="locale" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<>
|
||||
<LocaleField
|
||||
id={`configure-locale-${input.name}`}
|
||||
disabled={props.disabled}
|
||||
{...input}
|
||||
/>
|
||||
<ValidationMessage meta={meta} fullWidth />
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
</HorizontalGutter>
|
||||
</FormField>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
settings: graphql`
|
||||
fragment LocaleConfigContainer_settings on Settings {
|
||||
locale
|
||||
}
|
||||
`,
|
||||
})(LocaleConfigContainer);
|
||||
|
||||
export default enhanced;
|
||||
@@ -118,6 +118,81 @@ exports[`renders configure general 1`] = `
|
||||
className="Box-root HorizontalGutter-root HorizontalGutter-double"
|
||||
data-testid="configure-generalContainer"
|
||||
>
|
||||
<div
|
||||
className="Box-root HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Box-root HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<label
|
||||
className="Box-root Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
|
||||
htmlFor="configure-locale-locale"
|
||||
>
|
||||
Language
|
||||
</label>
|
||||
<p
|
||||
className="Box-root Typography-root Typography-detail Typography-colorTextPrimary"
|
||||
>
|
||||
Choose the language for your Coral community.
|
||||
</p>
|
||||
<span
|
||||
className="SelectField-root"
|
||||
>
|
||||
<select
|
||||
className="SelectField-select"
|
||||
disabled={false}
|
||||
id="configure-locale-locale"
|
||||
name="locale"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
value="en-US"
|
||||
>
|
||||
<option
|
||||
value="en-US"
|
||||
>
|
||||
English
|
||||
</option>
|
||||
<option
|
||||
value="pt-BR"
|
||||
>
|
||||
Português brasileiro
|
||||
</option>
|
||||
<option
|
||||
value="es"
|
||||
>
|
||||
Español
|
||||
</option>
|
||||
<option
|
||||
value="de"
|
||||
>
|
||||
Deutsch
|
||||
</option>
|
||||
<option
|
||||
value="nl-NL"
|
||||
>
|
||||
Nederlands
|
||||
</option>
|
||||
<option
|
||||
value="da"
|
||||
>
|
||||
Dansk
|
||||
</option>
|
||||
</select>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="SelectField-afterWrapper"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
expand_more
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset
|
||||
className="Box-root HorizontalGutter-root HorizontalGutter-oneAndAHalf"
|
||||
>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { SinonStub } from "sinon";
|
||||
|
||||
import { ERROR_CODES } from "coral-common/errors";
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { InvalidRequestError } from "coral-framework/lib/errors";
|
||||
@@ -63,6 +65,48 @@ it("renders configure general", async () => {
|
||||
expect(within(configureContainer).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("change language", async () => {
|
||||
const resolvers = createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
updateSettings: ({ variables }) => {
|
||||
expectAndFail(variables.settings.locale).toEqual("es");
|
||||
return {
|
||||
settings: pureMerge(settings, variables.settings),
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
const {
|
||||
context: { changeLocale },
|
||||
configureContainer,
|
||||
generalContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({ resolvers });
|
||||
|
||||
const languageField = within(generalContainer).getByLabelText("Language");
|
||||
|
||||
// Let's change the language.
|
||||
languageField.props.onChange("es");
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
|
||||
// Wait for client to change language.
|
||||
await wait(() => {
|
||||
expect((changeLocale as SinonStub).called).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("change site wide commenting", async () => {
|
||||
const resolvers = createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
|
||||
@@ -24,6 +24,7 @@ export const settings = createFixture<GQLSettings>({
|
||||
id: "settings",
|
||||
moderation: GQLMODERATION_MODE.POST,
|
||||
premodLinksEnable: false,
|
||||
locale: "en-US",
|
||||
live: {
|
||||
enabled: true,
|
||||
configurable: true,
|
||||
|
||||
Reference in New Issue
Block a user