Skip to content

Commit

Permalink
Add support for new languages (#181)
Browse files Browse the repository at this point in the history
Signed-off-by: Liam McLoughlin <lmcloughlin@fitbit.com>
  • Loading branch information
Hexxeh committed Jan 28, 2020
1 parent b7839d7 commit 3ffae30
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 47 deletions.
4 changes: 2 additions & 2 deletions src/ProjectConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ it('validationErrors() validates all fields', () => {
expect.objectContaining({
category: DiagnosticCategory.Error,
messageText:
'Default language is an invalid language tag: _invalid_. Must be de-DE, en-US, es-ES, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, sv-SE, zh-CN or zh-TW.',
'Default language is an invalid language tag: _invalid_. Must be en-US, de-DE, es-ES, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, sv-SE, zh-CN, zh-TW, pt-BR, id-ID, ro-RO, ru-RU, pl-PL or cs-CZ.',
}),
expect.objectContaining({
category: DiagnosticCategory.Error,
Expand Down Expand Up @@ -452,7 +452,7 @@ it('validates the default language is a valid language tag', () => {
expect.objectContaining({
category: DiagnosticCategory.Error,
messageText:
'Default language is an invalid language tag: _really_not_bcp_47_. Must be de-DE, en-US, es-ES, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, sv-SE, zh-CN or zh-TW.',
'Default language is an invalid language tag: _really_not_bcp_47_. Must be en-US, de-DE, es-ES, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, sv-SE, zh-CN, zh-TW, pt-BR, id-ID, ro-RO, ru-RU, pl-PL or cs-CZ.',
}),
);
});
Expand Down
30 changes: 15 additions & 15 deletions src/ProjectConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import semver from 'semver';

import buildTargets from './buildTargets';
import DiagnosticList from './DiagnosticList';
import { supportedTags, validateLanguageTag } from './languageTag';
import { validateLanguageTag } from './languageTag';
import sdkVersion from './sdkVersion';

const knownBuildTargets = Object.keys(buildTargets);
Expand Down Expand Up @@ -49,7 +49,7 @@ export default ProjectConfiguration;

export const MAX_DISPLAY_NAME_LENGTH = 30;

enum Locales {
export enum Locales {
'en-US' = 'English (US)',
'de-DE' = 'German',
'es-ES' = 'Spanish',
Expand All @@ -61,8 +61,16 @@ enum Locales {
'sv-SE' = 'Swedish',
'zh-CN' = 'Chinese (Simplified)',
'zh-TW' = 'Chinese (Traditional)',
'pt-BR' = 'Portuguese (Brazillian)',
'id-ID' = 'Indonesian (Bahasa)',
'ro-RO' = 'Romanian',
'ru-RU' = 'Russian',
'pl-PL' = 'Polish',
'cs-CZ' = 'Czech',
}

const languageTags = Object.keys(Locales);

enum Permission {
ACCESS_ACTIVITY = 'access_activity',
ACCESS_AOD = 'access_aod',
Expand Down Expand Up @@ -249,18 +257,10 @@ export function normalizeLocales(locales: LocalesConfig) {
* for all languages they'll quickly exceed this. This code merges the language
* tag into a locale tag unless one is present.
*/
const localeMapping: Record<string, string | undefined> = {
en: 'en-US',
de: 'de-DE',
it: 'it-IT',
es: 'es-ES',
fr: 'fr-FR',
ja: 'ja-JP',
ko: 'ko-KR',
nl: 'nl-NL',
sv: 'sv-SE',
};

const localeMapping: Record<string, string | undefined> = lodash.mapKeys(
Object.keys(Locales),
(tag) => tag.split('-')[0],
);
const normalizedLocales: LocalesConfig = {};

for (const [locale, localeConfig] of Object.entries(locales)) {
Expand Down Expand Up @@ -474,7 +474,7 @@ export function validateDefaultLanguage(config: ProjectConfiguration) {
diagnostics.pushFatalError(
`Default language is an invalid language tag: ${
config.defaultLanguage
}. Must be ${humanizeList(supportedTags, { conjunction: 'or' })}.`,
}. Must be ${humanizeList(languageTags, { conjunction: 'or' })}.`,
);
}
return diagnostics;
Expand Down
6 changes: 3 additions & 3 deletions src/__snapshots__/compileTranslations.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PluginError {
exports[`rejects .po files whose names are not acceptable language tags e.po 1`] = `
PluginError {
"fileName": "e.po",
"message": "Translation file e.po has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.",
"message": "Translation file e.po has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.",
"name": "Error",
"plugin": "compileTranslations",
}
Expand All @@ -47,7 +47,7 @@ PluginError {
exports[`rejects .po files whose names are not acceptable language tags en-USA.po 1`] = `
PluginError {
"fileName": "en-USA.po",
"message": "Translation file en-USA.po has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.",
"message": "Translation file en-USA.po has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.",
"name": "Error",
"plugin": "compileTranslations",
}
Expand All @@ -56,7 +56,7 @@ PluginError {
exports[`rejects .po files whose names are not acceptable language tags sl-IT-nedis.po 1`] = `
PluginError {
"fileName": "sl-IT-nedis.po",
"message": "Translation file sl-IT-nedis.po has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.",
"message": "Translation file sl-IT-nedis.po has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.",
"name": "Error",
"plugin": "compileTranslations",
}
Expand Down
14 changes: 9 additions & 5 deletions src/compile.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path';

import semver from 'semver';
import { SourceMapConsumer } from 'source-map';
import ts from 'typescript';
import Vinyl from 'vinyl';
Expand All @@ -12,16 +13,19 @@ import getVinylContents from './testUtils/getVinylContents';
import { ComponentType } from './componentTargets';
import { cwdSerializer } from './jestSnapshotSerializers';

jest.mock('./sdkVersion');

expect.addSnapshotSerializer(cwdSerializer);

let mockDiagnosticHandler: jest.Mock;
const mockSDKVersion = sdkVersion as jest.Mock;

jest.mock('./sdkVersion', () => jest.fn(() => semver.parse('4.2.0')));

function mockSDKVersion(version: string) {
(sdkVersion as jest.Mock).mockReturnValue(semver.parse(version));
}

beforeEach(() => {
mockDiagnosticHandler = jest.fn();
mockSDKVersion.mockReturnValue({ major: 4, minor: 1 });
mockSDKVersion('4.2.0');

// We don't want to load the actual tsconfig.json for this project
// during unit tests. Using a real tsconfig.json located within
Expand Down Expand Up @@ -196,6 +200,7 @@ describe('when building a device component which uses the gettext polyfill', ()
let file: string;

beforeEach(async () => {
mockSDKVersion('4.1.0');
file = await compileFile('i18n.js', {
component: ComponentType.DEVICE,
}).then(getVinylContents);
Expand All @@ -211,7 +216,6 @@ describe('when building a device component which uses the i18n API without requi
let file: string;

beforeEach(async () => {
mockSDKVersion.mockReturnValue({ major: 4, minor: 2 });
file = await compileFile('i18n.js', {
component: ComponentType.DEVICE,
}).then(getVinylContents);
Expand Down
5 changes: 3 additions & 2 deletions src/compileTranslations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import humanizeList from 'humanize-list';
import PluginError from 'plugin-error';
import Vinyl from 'vinyl';

import { validateLanguageTag, supportedTags } from './languageTag';
import { validateLanguageTag } from './languageTag';
import { Locales } from './ProjectConfiguration';

const PLUGIN_NAME = 'compileTranslations';

Expand Down Expand Up @@ -36,7 +37,7 @@ export default function compileTranslations(defaultLanguage: string) {
`Translation file ${
file.basename
} has a bad name. Translation files must be named ${humanizeList(
supportedTags.map((tag) => tag + '.po'),
Object.keys(Locales).map((tag) => tag + '.po'),
{ conjunction: 'or' },
)}.`,
{ fileName: file.relative },
Expand Down
16 changes: 2 additions & 14 deletions src/languageTag.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
export const supportedTags = [
'de-DE',
'en-US',
'es-ES',
'fr-FR',
'it-IT',
'ja-JP',
'ko-KR',
'nl-NL',
'sv-SE',
'zh-CN',
'zh-TW',
];
import { Locales } from './ProjectConfiguration';

export function validateLanguageTag(tagString: string) {
return supportedTags.includes(tagString);
return Object.keys(Locales).includes(tagString);
}
8 changes: 4 additions & 4 deletions src/plugins/__snapshots__/companionTranslations.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ exports[`throws if the default language is not found 1`] = `[Error: No translati

exports[`throws when a translation file has multiple msgstr values for the same msgid 1`] = `[Error: msgid "foo" in file "<base>/multiple-msgstr/en-US.po" has multiple msgstr values. This is not supported.]`;
exports[`throws when encountering the badly named file ".po" 1`] = `[Error: Translation file "<base>/bad-name/.po" has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.]`;
exports[`throws when encountering the badly named file ".po" 1`] = `[Error: Translation file "<base>/bad-name/.po" has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.]`;
exports[`throws when encountering the badly named file "a.po" 1`] = `[Error: Translation file "<base>/bad-name/a.po" has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.]`;
exports[`throws when encountering the badly named file "a.po" 1`] = `[Error: Translation file "<base>/bad-name/a.po" has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.]`;
exports[`throws when encountering the badly named file "english.po" 1`] = `[Error: Translation file "<base>/bad-name/english.po" has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.]`;
exports[`throws when encountering the badly named file "english.po" 1`] = `[Error: Translation file "<base>/bad-name/english.po" has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.]`;
exports[`throws when encountering the badly named file "enus.po" 1`] = `[Error: Translation file "<base>/bad-name/enus.po" has a bad name. Translation files must be named de-DE.po, en-US.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po or zh-TW.po.]`;
exports[`throws when encountering the badly named file "enus.po" 1`] = `[Error: Translation file "<base>/bad-name/enus.po" has a bad name. Translation files must be named en-US.po, de-DE.po, es-ES.po, fr-FR.po, it-IT.po, ja-JP.po, ko-KR.po, nl-NL.po, sv-SE.po, zh-CN.po, zh-TW.po, pt-BR.po, id-ID.po, ro-RO.po, ru-RU.po, pl-PL.po or cs-CZ.po.]`;
exports[`throws when multiple files map to the same language 1`] = `[Error: More than one translation file found for language en-US. Found "<base>/language-collision/en-US.po" and "<base>/language-collision/lang/en-US.po".]`;
5 changes: 3 additions & 2 deletions src/plugins/companionTranslations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import pofile from 'pofile';
import { dataToEsm } from '@rollup/pluginutils';

import BuildError from '../util/BuildError';
import { validateLanguageTag, supportedTags } from '../languageTag';
import { validateLanguageTag } from '../languageTag';
import { Locales } from '../ProjectConfiguration';

const glob = promisify(_glob);
const loadPOFile = promisify(pofile.load);
Expand Down Expand Up @@ -43,7 +44,7 @@ export default function companionTranslations(
if (!validateLanguageTag(languageTag)) {
throw new BuildError(
`Translation file "${filePath}" has a bad name. Translation files must be named ${humanizeList(
supportedTags.map((tag) => tag + '.po'),
Object.keys(Locales).map((tag) => tag + '.po'),
{ conjunction: 'or' },
)}.`,
);
Expand Down

0 comments on commit 3ffae30

Please sign in to comment.