From 361dcebc75dea74947b6c3aafd9d7d720c054b01 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 Feb 2020 15:51:19 +0100 Subject: [PATCH] Support i18n build --- client/angular.json | 167 ++++++++++++++++++++++++- client/package.json | 2 + client/src/app/app.module.ts | 13 +- client/src/environments/environment.ts | 3 +- client/src/main.ts | 28 ++--- client/tsconfig.app.json | 5 +- client/yarn.lock | 54 +++++++- scripts/build/client.sh | 40 ++++-- scripts/dev/client.sh | 2 +- 9 files changed, 264 insertions(+), 50 deletions(-) diff --git a/client/angular.json b/client/angular.json index f3f146bcb..bf3a860aa 100644 --- a/client/angular.json +++ b/client/angular.json @@ -7,12 +7,108 @@ "root": "", "sourceRoot": "src", "projectType": "application", + "i18n": { + "sourceLocale": "en", + "locales": { + "hu": { + "translation": "src/locale/angular.hu-HU.xlf", + "baseHref": "/" + }, + "th": { + "translation": "src/locale/angular.th-TH.xlf", + "baseHref": "/" + }, + "fi": { + "translation": "src/locale/angular.fi-FI.xlf", + "baseHref": "/" + }, + "nl": { + "translation": "src/locale/angular.nl-NL.xlf", + "baseHref": "/" + }, + "gd": { + "translation": "src/locale/angular.gd.xlf", + "baseHref": "/" + }, + "el": { + "translation": "src/locale/angular.el-GR.xlf", + "baseHref": "/" + }, + "es": { + "translation": "src/locale/angular.es-ES.xlf", + "baseHref": "/" + }, + "oc": { + "translation": "src/locale/angular.oc.xlf", + "baseHref": "/" + }, + "pt": { + "translation": "src/locale/angular.pt-BR.xlf", + "baseHref": "/" + }, + "pt-PT": { + "translation": "src/locale/angular.pt-PT.xlf", + "baseHref": "/" + }, + "sv": { + "translation": "src/locale/angular.sv-SE.xlf", + "baseHref": "/" + }, + "pl": { + "translation": "src/locale/angular.pl-PL.xlf", + "baseHref": "/" + }, + "ru": { + "translation": "src/locale/angular.ru-RU.xlf", + "baseHref": "/" + }, + "zh-Hans": { + "translation": "src/locale/angular.zh-Hans-CN.xlf", + "baseHref": "/" + }, + "zh-Hant": { + "translation": "src/locale/angular.zh-Hant-TW.xlf", + "baseHref": "/" + }, + "fr": { + "translation": "src/locale/angular.fr-FR.xlf", + "baseHref": "/" + }, + "ja": { + "translation": "src/locale/angular.ja-JP.xlf", + "baseHref": "/" + }, + "eu": { + "translation": "src/locale/angular.eu-ES.xlf", + "baseHref": "/" + }, + "ca": { + "translation": "src/locale/angular.ca-ES.xlf", + "baseHref": "/" + }, + "cs": { + "translation": "src/locale/angular.cs-CZ.xlf", + "baseHref": "/" + }, + "eo": { + "translation": "src/locale/angular.eo.xlf", + "baseHref": "/" + }, + "de": { + "translation": "src/locale/angular.de-DE.xlf", + "baseHref": "/" + }, + "it": { + "translation": "src/locale/angular.it-IT.xlf", + "baseHref": "/" + } + } + }, "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "aot": true, - "deployUrl": "client/", "outputPath": "dist", "index": "src/index.html", "main": "src/main.ts", @@ -91,6 +187,75 @@ "with": "src/environments/environment.e2e.ts" } ] + }, + "hu-HU": { + "localize": [ "hu" ] + }, + "th-TH": { + "localize": [ "th" ] + }, + "fi-FI": { + "localize": [ "fi" ] + }, + "nl-NL": { + "localize": [ "nl" ] + }, + "gd": { + "localize": [ "gd" ] + }, + "el-GR": { + "localize": [ "el" ] + }, + "es-ES": { + "localize": [ "es" ] + }, + "oc": { + "localize": [ "oc" ] + }, + "pt-BR": { + "localize": [ "pt" ] + }, + "pt-PT": { + "localize": [ "pt-PT" ] + }, + "sv-SE": { + "localize": [ "sv" ] + }, + "pl-PL": { + "localize": [ "pl" ] + }, + "ru-RU": { + "localize": [ "ru" ] + }, + "zh-Hans-CN": { + "localize": [ "zh-Hans" ] + }, + "zh-Hant-TW": { + "localize": [ "zh-Hant" ] + }, + "fr-FR": { + "localize": [ "fr" ] + }, + "ja-JP": { + "localize": [ "ja" ] + }, + "eu-ES": { + "localize": [ "eu" ] + }, + "ca-ES": { + "localize": [ "ca" ] + }, + "cs-CZ": { + "localize": [ "cs" ] + }, + "eo": { + "localize": [ "eo" ] + }, + "de-DE": { + "localize": [ "de" ] + }, + "it-IT": { + "localize": [ "it" ] } } }, diff --git a/client/package.json b/client/package.json index de5c0182b..9da34e4e8 100644 --- a/client/package.json +++ b/client/package.json @@ -48,6 +48,8 @@ "@angular/router": "~9.0.0", "@angular/service-worker": "~9.0.0", "@angularclass/hmr": "^2.1.3", + "@locl/cli": "^0.0.1-beta.5", + "@locl/core": "^0.0.1-beta.2", "@neos21/bootstrap3-glyphicons": "^1.0.1", "@ng-bootstrap/ng-bootstrap": "^5.2.1", "@ngx-i18nsupport/ngx-i18nsupport": "^1.1.6", diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index 62915ec54..14fdb7588 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts @@ -4,7 +4,6 @@ import { ServerService } from '@app/core' import { ResetPasswordModule } from '@app/reset-password' import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core' -import { ClipboardModule } from 'ngx-clipboard' import 'focus-visible' import { AppRoutingModule } from './app-routing.module' @@ -15,11 +14,10 @@ import { LoginModule } from './login' import { AvatarNotificationComponent, LanguageChooserComponent, MenuComponent } from './menu' import { SharedModule } from './shared' import { VideosModule } from './videos' -import { buildFileLocale, getCompleteLocale, isDefaultLocale } from '../../../shared/models/i18n' -import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' import { SearchModule } from '@app/search' import { WelcomeModalComponent } from '@app/modal/welcome-modal.component' import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' +import { buildFileLocale, getCompleteLocale, isDefaultLocale } from '@shared/models' export function metaFactory (serverService: ServerService): MetaLoader { return new MetaStaticLoader({ @@ -67,17 +65,12 @@ export function metaFactory (serverService: ServerService): MetaLoader { AppRoutingModule // Put it after all the module because it has the 404 route ], + providers: [ { provide: TRANSLATIONS, useFactory: (locale: string) => { - // On dev mode, test localization - if (isOnDevLocale()) { - locale = buildFileLocale(getDevLocale()) - return require(`raw-loader!../locale/angular.${locale}.xlf`) - } - - // Default locale, nothing to translate + // Default locale, nothing to translate const completeLocale = getCompleteLocale(locale) if (isDefaultLocale(completeLocale)) return '' diff --git a/client/src/environments/environment.ts b/client/src/environments/environment.ts index 1ea483554..b6bc784b5 100644 --- a/client/src/environments/environment.ts +++ b/client/src/environments/environment.ts @@ -6,8 +6,7 @@ // // In order to load these polyfills early enough (before app code), polyfill.ts imports this file to // to change the order in the final bundle. -import 'core-js/es6/reflect' -import 'core-js/es7/reflect' +import 'core-js/features/reflect' export const environment = { production: false, diff --git a/client/src/main.ts b/client/src/main.ts index 2b65072ad..3fb9b346e 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -1,31 +1,17 @@ -import { enableProdMode, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core' +import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' import { environment } from './environments/environment' import { hmrBootstrap } from './hmr' -import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' -import { buildFileLocale } from '../../shared' -let providers: any[] = [] if (environment.production) { enableProdMode() } -// Template translation, should be in the bootstrap step -if (isOnDevLocale()) { - const locale = buildFileLocale(getDevLocale()) - const translations = require(`raw-loader!./locale/angular.${locale}.xlf`) - - providers = [ - { provide: TRANSLATIONS, useValue: translations }, - { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' } - ] -} - const bootstrap = () => platformBrowserDynamic() - .bootstrapModule(AppModule, { providers }) + .bootstrapModule(AppModule) .then(bootstrapModule => { // TODO: Uncomment and remove unregistration when https://github.com/angular/angular/issues/21191 is fixed // TODO: Remove when https://github.com/angular/angular-cli/issues/8779 is fixed? @@ -36,11 +22,11 @@ const bootstrap = () => platformBrowserDynamic() if (navigator.serviceWorker && typeof navigator.serviceWorker.getRegistrations === 'function') { navigator.serviceWorker.getRegistrations() - .then(registrations => { - for (const registration of registrations) { - registration.unregister() - } - }) + .then(registrations => { + for (const registration of registrations) { + registration.unregister() + } + }) } return bootstrapModule diff --git a/client/tsconfig.app.json b/client/tsconfig.app.json index 225555bfc..d7f69a98e 100644 --- a/client/tsconfig.app.json +++ b/client/tsconfig.app.json @@ -12,12 +12,11 @@ ] }, "files": [ - "src/main.ts", "src/polyfills.ts" ], "include": [ + "src/main*.ts", "src/**/*.d.ts", - "src/shims/*.ts", - "../shared/models" + "src/shims/*.ts" ] } diff --git a/client/yarn.lock b/client/yarn.lock index 536bd1f99..a891b4dbd 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -286,7 +286,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.7.5": +"@babel/core@^7.6.4", "@babel/core@^7.7.5": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== @@ -1031,6 +1031,22 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== +"@locl/cli@^0.0.1-beta.5": + version "0.0.1-beta.5" + resolved "https://registry.yarnpkg.com/@locl/cli/-/cli-0.0.1-beta.5.tgz#9e9d970b4db6282ecda76503d525ffa9aa276a0d" + integrity sha512-eF2WN61aZaojHODo/NsO1ndeH0+7tQhUH0KYmfubjRPSQwsh1trMDKIKHkzZYQQQBNOzCZOGzZHnK7EaWwWkow== + dependencies: + "@babel/core" "^7.6.4" + chalk "^3.0.0" + find-up "^4.1.0" + glob "^7.1.2" + yargs "^13.1.0" + +"@locl/core@^0.0.1-beta.2": + version "0.0.1-beta.2" + resolved "https://registry.yarnpkg.com/@locl/core/-/core-0.0.1-beta.2.tgz#2055bae5e1d276d75a6aeb7e0944c72848c00f65" + integrity sha512-R33xL9Z/VtXSCh9zv8qiGVV92zOJZJnH7vyXVRxhuFtpt7cL7sKbCNrZc966722Gu0LCpQ9MXERki2bl1vxjkg== + "@neos21/bootstrap3-glyphicons@^1.0.1": version "1.0.3" resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.3.tgz#58ecfeed21a959875077f190acc191b2d0e60aa6" @@ -1149,6 +1165,11 @@ dependencies: "@types/node" "*" +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/core-js@^2.5.2": version "2.5.2" resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.2.tgz#d4c25420044d4a5b65e00a82fc04b7824b62691f" @@ -1747,6 +1768,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -2650,6 +2679,14 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2918,12 +2955,19 @@ color-convert@^1.9.0, color-convert@^1.9.1, color-convert@^1.9.3: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -4747,7 +4791,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -10853,7 +10897,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== @@ -12242,7 +12286,7 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" -yargs@^13.2.4: +yargs@^13.1.0, yargs@^13.2.4: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== diff --git a/scripts/build/client.sh b/scripts/build/client.sh index ee647bb99..99394838a 100755 --- a/scripts/build/client.sh +++ b/scripts/build/client.sh @@ -2,6 +2,8 @@ set -eu +declare -A languages + pre_build_hook () { mkdir "./src/pending_locale" > /dev/null || true mv ./src/locale/angular.*.xlf "./src/pending_locale" @@ -38,22 +40,46 @@ post_build_hook # Don't build other languages if --light arg is provided if [ -z ${1+x} ] || [ "$1" != "--light" ]; then if [ ! -z ${1+x} ] && [ "$1" == "--light-fr" ]; then - languages=("fr-FR") + languages=(["fr"]="fr-FR") else # Supported languages languages=( - "hu-HU" "th-TH" - "fi-FI" "nl-NL" "gd" "el-GR" "es-ES" "oc" "pt-BR" "pt-PT" "sv-SE" "pl-PL" "ru-RU" "zh-Hans-CN" "zh-Hant-TW" - "fr-FR" "ja-JP" "eu-ES" "ca-ES" "cs-CZ" "eo" "de-DE" "it-IT" + ["hu"]="hu-HU" + ["th"]="th-TH" + ["fi"]="fi-FI" + ["nl"]="nl-NL" + ["gd"]="gd" + ["el"]="el-GR" + ["es"]="es-ES" + ["oc"]="oc" + ["pt"]="pt-BR" + ["pt-PT"]="pt-PT" + ["sv"]="sv-SE" + ["pl"]="pl-PL" + ["ru"]="ru-RU" + ["zh-Hans"]="zh-Hans-CN" + ["zh-Hant"]="zh-Hant-TW" + ["fr"]="fr-FR" + ["ja"]="ja-JP" + ["eu"]="eu-ES" + ["ca"]="ca-ES" + ["cs"]="cs-CZ" + ["eo"]="eo" + ["de"]="de-DE" + ["it"]="it-IT" ) fi - for lang in "${languages[@]}"; do + for key in "${!languages[@]}"; do + lang=${languages[$key]} + # TODO: remove when the project will use runtime translations pre_build_hook "$lang" - npm run ng build -- --prod --i18n-file "./src/locale/angular.$lang.xlf" --i18n-format xlf --i18n-locale "$lang" \ - --output-path "dist/$lang/" --deploy-url "/client/$lang/" + npm run ng build -- --output-path "dist/build" --deploy-url "/client/$lang/" --prod --configuration="$lang" + + mv "dist/build/$key" "dist/$lang" + rmdir "dist/build" # Do not duplicate assets rm -r "./dist/$lang/assets" diff --git a/scripts/dev/client.sh b/scripts/dev/client.sh index bcb8b88f6..a36a47a34 100755 --- a/scripts/dev/client.sh +++ b/scripts/dev/client.sh @@ -2,7 +2,7 @@ set -eu -clientCommand="cd client && node node_modules/.bin/ng serve --proxy-config proxy.config.json --hmr --configuration hmr --host 0.0.0.0 --disable-host-check --port 3000" +clientCommand="cd client && node node_modules/.bin/ng serve --proxy-config proxy.config.json --hmr --configuration hmr,fr --host 0.0.0.0 --disable-host-check --port 3000" serverCommand="npm run build:server && NODE_ENV=test node dist/server" if [ ! -z ${1+x} ] && [ "$1" == "--skip-server" ]; then -- 2.25.1