[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:
Wyatt Johnson
2019-09-05 17:02:06 +00:00
committed by GitHub
parent 5bf4f22931
commit 04c56b3fb5
54 changed files with 673 additions and 207 deletions
@@ -0,0 +1,43 @@
import { Kind } from "graphql";
import Locale from "./locale";
describe("parseLiteral", () => {
it("parses a valid locale from a string", () => {
expect(
Locale.parseLiteral({
kind: Kind.STRING,
value: "en-US",
})
).toBe("en-US");
});
it("parses an unsupported locale from a string", () => {
expect(() =>
Locale.parseLiteral({
kind: Kind.STRING,
value: "xyz",
})
).toThrow();
});
it("throws when not a string", () => {
expect(() =>
Locale.parseLiteral({
kind: Kind.INT,
value: "4",
})
).toThrow();
});
});
describe("parseValue", () => {
it("parses a valid locale from a string", () => {
expect(Locale.parseValue("en-US")).toBe("en-US");
});
it("parses an unsupported locale from a string", () => {
expect(() => Locale.parseValue("xyz")).toThrow();
});
it("throws when not a string", () => {
expect(() => Locale.parseValue(4)).toThrow();
});
});
@@ -0,0 +1,32 @@
import { LOCALES } from "coral-common/helpers/i18n";
import { GraphQLScalarType } from "graphql";
import { Kind } from "graphql/language";
function assertSupportLocale(locale: string) {
if (!LOCALES.includes(locale as any)) {
throw new Error(`Supported locales are ${JSON.stringify(LOCALES)}`);
}
}
export default new GraphQLScalarType({
name: "Locale",
description: "Locale represents a language code in the BCP 47 format.",
serialize(value) {
return value;
},
parseValue(value) {
if (typeof value !== "string") {
throw new Error("Locale must be a string in BCP 47 format.");
}
assertSupportLocale(value);
return value;
},
parseLiteral(ast) {
if (ast.kind !== Kind.STRING) {
throw new Error("Locale must be a string in BCP 47 format.");
}
const value = ast.value.toString();
assertSupportLocale(value);
return value;
},
});
@@ -1,28 +0,0 @@
import { LanguageCode } from "coral-common/helpers/i18n/locales";
import { GQLLOCALES } from "../schema/__generated__/types";
import { LOCALES } from "./LOCALES";
it("does not contain duplicate entries", () => {
const seen: Partial<Record<LanguageCode, true>> = {};
for (const key in LOCALES) {
if (!LOCALES.hasOwnProperty(key)) {
continue;
}
const value = LOCALES[key as GQLLOCALES];
expect(value in seen).toBeFalsy();
seen[value] = true;
}
});
it("contains the correct mappings to the BCP 47 format", () => {
for (const key in LOCALES) {
if (!LOCALES.hasOwnProperty(key)) {
continue;
}
const value = LOCALES[key as GQLLOCALES];
expect(value).toEqual(key.replace(/_/, "-"));
}
});
@@ -1,10 +0,0 @@
import { LanguageCode } from "coral-common/helpers/i18n/locales";
import { GQLLOCALES } from "../schema/__generated__/types";
export const LOCALES: Record<GQLLOCALES, LanguageCode> = {
en_US: "en-US",
pt_BR: "pt-BR",
es: "es",
de: "de",
};
@@ -1,4 +1,5 @@
import Cursor from "coral-server/graph/common/scalars/cursor";
import Locale from "coral-server/graph/common/scalars/locale";
import Time from "coral-server/graph/common/scalars/time";
import { GQLResolver } from "coral-server/graph/tenant/schema/__generated__/types";
@@ -81,6 +82,7 @@ const Resolvers: GQLResolver = {
UsernameHistory,
Tag,
Time,
Locale,
User,
UserStatus,
UsernameStatus,
+1 -17
View File
@@ -1,14 +1,8 @@
import {
addResolveFunctionsToSchema,
attachDirectiveResolvers,
IEnumResolver,
IResolvers,
} from "graphql-tools";
import { attachDirectiveResolvers, IResolvers } from "graphql-tools";
import { loadSchema } from "coral-common/graphql";
import auth from "coral-server/graph/common/directives/auth";
import resolvers from "coral-server/graph/tenant/resolvers";
import { LOCALES } from "coral-server/graph/tenant/resolvers/LOCALES";
export default function getTenantSchema() {
const schema = loadSchema("tenant", resolvers as IResolvers);
@@ -16,15 +10,5 @@ export default function getTenantSchema() {
// Attach the directive resolvers.
attachDirectiveResolvers(schema, { auth });
// Attach the GraphQL enum fields.
addResolveFunctionsToSchema({
schema,
resolvers: {
// For some reason, the resolver doesn't quite work without coercing the
// type.
LOCALES: LOCALES as IEnumResolver,
},
});
return schema;
}
@@ -68,6 +68,11 @@ Cursor represents a paginating cursor.
"""
scalar Cursor
"""
Locale represents a language code in the BCP 47 format.
"""
scalar Locale
################################################################################
## Actions
################################################################################
@@ -990,17 +995,6 @@ type StoryMessageBox {
## Settings
################################################################################
"""
LOCALES list all the supported locales in a modified BCP 47 format, where the
hyphen is replaced by an underscore.
"""
enum LOCALES {
en_US
pt_BR
es
de
}
"""
CloseCommenting contains settings related to the automatic closing of commenting
on Stories.
@@ -1124,7 +1118,7 @@ type Settings {
"""
locale is the specified locale for this Tenant.
"""
locale: LOCALES!
locale: Locale!
"""
live provides configuration options related to live updates for stories on
@@ -3371,6 +3365,11 @@ input SettingsInput {
accountFeatures specifies the configuration for accounts.
"""
accountFeatures: CommenterAccountFeaturesInput
"""
locale specifies the locale for this Tenant.
"""
locale: Locale
}
"""