How To Use LOCALE_ID In Angular i18n Router Module

China☆狼群 提交于 2021-02-18 11:40:47

问题


Im building a small Angular Application with Angular's i18n setup. Everything ist working fine, except for the translations of the url paths and slugs. I tried a possible solution with providing a routing module per language (as described here), but this did not work.

I thought that I could do something like the following, but I can't figure out where to inject LOCALE_ID:

app-routing.module.ts

import { LOCALE_ID, NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MainComponent } from './main/main.component';

const i18nRoutes = {
    de: {
        main: 'inhalte',
        // ...
    }, 
    fr: {
        main: 'contenu',
        // ...
    }
}

const currentLanguage = i18nRoutes[ LOCALE_ID ]; // <-- Apparently not working, since I have to inject LOCALE_ID. But where?

const routes: Routes = [
    {
        path: '',
        redirectTo: currentLanguage.main,
        pathMatch: 'full'
    },
    {
        path: currentLanguage.main + '/:key',
        component: MainComponent
    }
    // ...
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Update for clarification

in angular.json, I set configurations for the building process in each language (taken from here, with a view modifications for 2018)

angular.json

{
    // ...
    "projects": {
        "my-app": {
            // ...
            "architect": {
                "build": {
                    // ...
                    "configurations": {
                        // ...
                        "de": {
                            "i18nFile": "src/i18n/de.xliff",
                            "outputPath": "dist/de",
                            "i18nFormat": "xlf",
                            "i18nLocale": "de",
                            "baseHref": "/de/"
                            // ...
                        },
                        "fr": {
                            "i18nFile": "src/i18n/fr.xliff",
                            "outputPath": "dist/fr",
                            "i18nFormat": "xlf",
                            "i18nLocale": "fr",                            
                            "baseHref": "/fr/",
                            // ...
                        }
                   }
              }
          }
     }
}

For building all apps at once, I then enter npm run buildall, which executes the following in package.json:

package.json

{
    "name": "my-app",
    // ...
    "scripts": {
        // ...
        "buildall": "for lang in de fr;do ng build --configuration=$lang; done"
    }
}

which generates all apps in a subdirectory in the dist folder just fine.

So, to come back to my original question: The provided answer by Exterminator does not fit my needs, since

  • I cannot set a fixed locale while bootstrapping
  • Injecting LOCALE_ID in the constructor is too late since I need the value in app-routing.module.ts

I hope I explained enough. But maybe I misunderstood something completely. In any case, thanks in advance for any help. I am still learning and I must admit that a few concepts are still blurry to me.


回答1:


I had the same exact problem and this is how I solved it.

I created an app-locale.ts file that only had one constant that it exports which can then be used for LOCALE_ID provider to set the locale id.

src/app/app-locale.ts

/*
    WARNING: This file is to help facilitate the auotmation of the build
    process. In order to set the locale during development, change
    the value by hand to the target locale. If the file name or 
    location is changed make sure to update the build scripts
    accordingly.
*/ 
export const APP_LOCALE_ID:string = "es-es";

I used the above constant in my app.module.ts to provide the LOCALE_ID.

src/app/app.module.ts

import { LOCALE_ID, NgModule, TRANSLATIONS, TRANSLATIONS_FORMAT } from "@angular/core";
import { APP_LOCALE_ID } from './app-locale';
...
providers: [{
      provide: TRANSLATIONS_FORMAT,
      useValue: "xlf"
    }, { 
      provide: TRANSLATIONS, 
      useFactory: (locale) => {
        locale = locale || 'en-US'; 
        return require(`raw-loader!../locale/messages.${locale}.xlf`);
      },
      deps: [LOCALE_ID] 
    }, {
      provide: LOCALE_ID,
      useValue: APP_LOCALE_ID
    }
  ],
  ...

Now I need a small script that would run before the build starts which will set the local id in the file app-locale.ts. So I wrote this small node script and put it in a separate "scripts" folder.

scripts/set-app-locale.js

const fs = require('fs');
const argv = require('minimist')(process.argv.slice(2));

var version = '0.0.1',
    appLocale = "en-US",
    appLocaleFile = "./src/app/app-locale.ts",
    help = `
Set the static locale for the app.
Usage: node <path>set-app-locale.js [options]

Options:
  --version         Show version number                                  [boolean]
  --help, -h        Show help                                            [boolean]
  --app-locale      Target locale id                                     [string]
  --app-locale-file                                                      [string]
                    Path and name of app-locale that contains only one constant which
                    is a const string that holds the locale value. 
                    [default: "${__dirname}/src/app/app-locale.ts"]   `;

var setArgs = function(){
    if (argv.version){
        console.log(version);
        return false;
    }
    if (argv.h || argv.help){
        console.log(help);
        return false;
    }
    appLocale = argv["app-locale"] || appLocale;
    appLocaleFile = argv["app-locale-file"] || appLocaleFile;
    return true;
}
var setLocale = function(locale){
    var fileData = 
`/*
    WARNING: This file is to help facilitate the automation of the build
    process. In order to set the locale during development, change
    the value by hand to the target locale. If the file name or 
    location is changed make sure to update the build scripts
    accordingly.
*/ 
export const APP_LOCALE_ID:string = "${locale}";`;
    fs.writeFile(appLocaleFile, fileData, function(err) {
        if(err) {
            return console.log(err);
        }
        console.log(`App locale changed to ${locale}`);
    }); 
}

setArgs() && setLocale(appLocale);

Next I would go ahead and change my package.json to include this to set the locale id.

package.json

....
"config": {"locales": "en-US es-es"},
  "scripts": {
    ...
    "i18n-build": "for lang in $npm_package_config_locales; do node ./scripts/set-app-locale.js --app-locale=$lang && ng build --prod --configuration=$lang; done"
  }
....

I use xliffmerge which is part of @ngx-i18nsupport. This helps me avoid overwriting previously extracted and translated strings every time I extract strings.

So now whenever I build the app for all the supported locales, the LOCALE_ID gets set appropriately. I am sure there must be other ways to solve this problem but this is how I solved it.




回答2:


add this to the app.module

providers: [{provide: LOCALE_ID, useValue: 'fr-FR'}]

then call it using the following method where ever you want

import {LOCALE_ID} from '@angular/core';

  constructor(@Inject(LOCALE_ID) locale: string){
    console.log('locale', locale);
  }

also you can use this method

platformBrowserDynamic([{provide: LOCALE_ID, useValue: 'en-EN'}]).bootstrapModule(AppModule, {providers: [{provide: LOCALE_ID, useValue: 'en-EN'}]});


来源:https://stackoverflow.com/questions/52333266/how-to-use-locale-id-in-angular-i18n-router-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!