Угловой 6 и i18n в машинописи - PullRequest
0 голосов
/ 19 сентября 2018

Я видел, что angular6 реализует i18n для своих компонентов и что с помощью i18n вы можете интернационализировать ваш html, но можете ли вы сделать то же самое с машинописью?У меня есть две конкретные области

Одна в zingChart: - Уметь i18n Пример

exampleData = {
 valueBox: {
                text: '<span style="font-size: 32px">%pie-total-value</span> <br/> Example',
                placement: 'center',
                fontWeight: 'normal'
            },
     }

Большое спасибо за ваше время и ответы.

Ответы [ 2 ]

0 голосов
/ 03 июня 2019

Вы можете расширить процесс «ng serve | build», чтобы выполнить «AOT compialtion» для перевода i18n в .ts@translationId) в .ts

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

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent {
      title = 'i18n-ts-demo-ng';
      title2 = '@@my.test.header';
    }
  • и перевести их в процессе сборки

    1. add "ng add ngx-build-plus"
    2. создать плагин
//create file i18n-plugin.ts in root
import { I18NTransformer } from './i18n';
import { AngularCompilerPlugin } from '@ngtools/webpack';

function findAngularCompilerPlugin(webpackCfg): AngularCompilerPlugin | null {
  return webpackCfg.plugins.find(plugin =>  plugin instanceof AngularCompilerPlugin);
}

// The AngularCompilerPlugin has nog public API to add transformations, user private API _transformers instead.
function addTransformerToAngularCompilerPlugin(acp, transformer): void {
  acp._transformers = [transformer, ...acp._transformers];
}

export default {
  pre() {
    // This hook is not used in our example
  },

  // This hook is used to manipulate the webpack configuration
  config(cfg) {
    // Find the AngularCompilerPlugin in the webpack configuration
    const angularCompilerPlugin = findAngularCompilerPlugin(cfg);

    if (!angularCompilerPlugin) {
      console.error('Could not inject the typescript transformer: Webpack AngularCompilerPlugin not found');
      return;
    }

    addTransformerToAngularCompilerPlugin(angularCompilerPlugin, I18NTransformer);
    return cfg;
  },

  post() {
    // This hook is not used in our example
  }
};
//create file i18n.ts in root
import * as ts from 'typescript';

// TODO move to config
const RequireAlli18NKeys = false; // if true onda all 18n keys must be found othervse error is thrown;

// Read translations
import { Xliff, Node } from '@angular/compiler';
const fs = require('fs');
const path = require('path');

let localeId: string; // hr || en ...

let i18nLocale = 0; // 0 - parameter not found | 1 - parameter is fount so next is locale string (hr, ...)

// parse parameters
process.argv.forEach(pParam => {

  console.log('param:' + pParam);
  // get Locale is using: ng serve ...
  if (pParam.startsWith('--configuration=')) {
    localeId = pParam.replace('--configuration=', '');
    console.log('Locale:' + localeId);
  }

  // Has to be before code down
  if (i18nLocale === 1) {
    i18nLocale = 2;
    localeId = pParam;
    console.log('Locale:' + localeId);
  }

  // Get locale if using: ng build --prod --i18n-locale en ...
  if (pParam.startsWith('--i18n-locale')) {
    i18nLocale = 1;
    localeId = pParam.replace('--config--i18n-locale ', '')
  }
});

// Load translation
// tslint:disable-next-line:max-line-length
if (localeId === undefined) { throw new Error(`No language specified.\nUsage: ng serve --configuration=hr --aot --plugin ~dist/out-tsc/i18n-plugin.js`); }
const content = fs.readFileSync(`src/translate/messages.${localeId}.xlf`, 'utf8');
const xliff = new Xliff().load(content, '');

export const I18NTransformer = <T extends ts.Node>(context: ts.TransformationContext) => {
  return (rootNode: ts.SourceFile) => {
    function visit(node: ts.Node): ts.Node {
      if (
        rootNode.fileName.includes('node_modules')
        || !rootNode.fileName.includes('.ts')
        // || ts.isToken(node)
      ) {
        return ts.visitEachChild(node, visit, context);
      }

      if (ts.isStringLiteral(node)) {
        // teplace @@ with translation
        if (node.text.includes('@@')) {
          // take key for translatioc
          const tSourceKey = node.text;
          const tI18NKey = node.text.replace('@@', '');
          // find key
          const tTranslation: any = xliff.i18nNodesByMsgId[tI18NKey];
          if (tTranslation) {
            // let t1 = tTranslation[0];

            // let tLocaleStr = t1.toString(); //tTranslation[0].value;
            const tLocaleStr = tTranslation[0].value;
            console.log(ConsoleColor.BgCyan, 'i18n key: ', ConsoleColor.Reset, tI18NKey + '=> translation   : ' + tLocaleStr);
            const tNew2 = node.text.replace(tSourceKey, tLocaleStr);
            return ts.createStringLiteral(tNew2);
          }
          const tMessage = 'ERROR! No translation for key: ' + tI18NKey + ', source:' + rootNode.fileName;
          console.log(ConsoleColor.BgRed, tMessage, ConsoleColor.Reset);
          if (RequireAlli18NKeys) {
            throw new Error(tMessage);
          }
        }
      }

      return ts.visitEachChild(node, visit, context);
    }
    return ts.visitNode(rootNode, visit);
  };
};

class ConsoleColor {
  static Reset = '\x1b[0m';
  static Bright = '\x1b[1m';
  static Dim = '\x1b[2m';
  static Underscore = '\x1b[4m';
  static Blink = '\x1b[5m';
  static Reverse = '\x1b[7m';
  static Hidden = '\x1b[8m';

  static FgBlack = '\x1b[30m';
  static FgRed = '\x1b[31m';
  static FgGreen = '\x1b[32m';
  static FgYellow = '\x1b[33m';
  static FgBlue = '\x1b[34m';
  static FgMagenta = '\x1b[35m';
  static FgCyan = '\x1b[36m';
  static FgWhite = '\x1b[37m';

  static BgBlack = '\x1b[40m';
  static BgRed = '\x1b[41m';
  static BgGreen = '\x1b[42m';
  static BgYellow = '\x1b[43m';
  static BgBlue = '\x1b[44m';
  static BgMagenta = '\x1b[45m';
  static BgCyan = '\x1b[46m';
  static BgWhite = '\x1b[47m';
}
  • при запуске терминала: tsc --skipLibCheck --module umd -w

  • ng serve --configuration = hr --aot --plugin ~ dist / out-tsc / i18n-plugin.js

полный пример в https://github.com/Emanuel3003/i18n-ts-demo-ng

Привет

0 голосов
/ 14 февраля 2019

Это невозможно через API библиотеки до сих пор (@angular/language-service v7.2).

Ниже представлен мой обходной путь (спасибо fredrikredflag за его хороший пост на GitHub и спасибо @BrunoBruzzano за ссылку ):


src/app/i18n.service.ts:

import {Injectable} from "@angular/core";
import {Xliff2} from '@angular/compiler';
// You can also import {Xliff} or {Xtb} instead of {Xliff2}, depending on your project configurations

declare const require;
const content = require('raw-loader!../i18n/messages.fa.xlf');

@Injectable({
    providedIn: 'root'
})
export class I18nService {
    private readonly xliff: any = new Xliff2().load(content, '');

    get(key: string): string {
        return this.xliff.i18nNodesByMsgId[key][0].value;
    }
}

Псевдо-компонент i18n (ТОЛЬКО ДЛЯ АВТО-ГЕНЕРАЦИОННЫХ ПЕРЕВОДОВ в файле messages.xlf) :

  1. src/app/i18n/i18n.component.ts (Не важно. Просто нужно для существования.):

    import {Component} from '@angular/core';
    @Component({templateUrl: './i18n.component.html'})
    export class I18nComponent {}
    
  2. src/app/i18n/i18n.component.html( не забудьте использовать идентификатор! )

    <p i18n="@@newVersionAlert">New version available. Load New Version?</p>
    

Не забудьте объявить I18nComponent в вашем @NgModule.


Использование (после выполнения ng xi18n ... и перевода):

В вашемкомпонент :

...
import {I18nService} from './i18n.service';

...
    constructor(private i18nService: I18nService, ...) { ... }

    sampleUsage() {
        confirm(this.t('newVersionAlert'));
    }

    /**
     * translate
     */
    private t(i18nId: string) {
        return this.i18nService.get(i18nId);
    }
...

Служебный скрипт для перевода i18n.service.ts перед сборкой :

(Это требование: require('raw-loader!../i18n/messages.fa.xlf') необходимо перевести в соответствии с желаемой локалью. )

PreBuild/prebuild.ts:

import {Xliff2} from "@angular/compiler";  
// You can also import {Xliff} or {Xtb} from "@angular/compiler" depending of your case.

const fs = require('fs');  
const path = require('path');  

const localeId = process.argv[2];  

if (localeId === undefined) throw new Error(`No language specified.\nUsage: node ${path.basename(__filename)} <locale-id${'>'}`);  

const content = fs.readFileSync(`src/i18n/messages.${localeId}.xlf`, 'utf8');  
const xliff = new Xliff2().load(content, '');

const i18nServiceFilePath = './src/app/i18n.service.ts'; 

fs.writeFileSync(i18nServiceFilePath,  
  fs.readFileSync(i18nServiceFilePath, 'utf8')  
    .replace(/(raw-loader!\.\.\/i18n\/messages\.)\w{2}(\.xlf)/, `$1${xliff.locale}$2`)  
);

PreBuild/tsconfig.json:

{
    "compilerOptions": {
        "outDir": "./build",
        "lib": [
            "es2018",
            "dom"
        ],
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "es6",
        "typeRoots": [
            "../node_modules/@types"
        ]
    },
    "files": [
        "prebuild.ts"
    ]
}

package.json:

...
"scripts": {
    "compile-pre-build": "tsc -p PreBuild/tsconfig.json --pretty",
    "pre-build": "node PreBuild/build/prebuild.js",
    ...
...

Использование:

(после однократного npm run compile-pre-build:)

npm run pre-build -- fa

или

npm run pre-build -- en

Это отредактирует i18n.service.ts.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...