Giter VIP home page Giter VIP logo

translate's People

Contributors

denysvuika avatar dependabot-preview[bot] avatar dependabot[bot] avatar mergify[bot] avatar osahner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

osahner whebz

translate's Issues

Support for routes

Hello,
Do you have any plans on supporting routes? I'm looking for an alternative for localize-router since it seems abandoned and has a bunch of bugs. Just wondering if I should keep an eye open for changes to this project.

Compile failed because of unknown pipe

I'm using ngstack/translate in an Angular/Ionic project. Although the application works, I do get errors in the IDE (IntelliJ), telling me that the pipe "translate" in unknown.

Now I tried the new Ivy renderer and do get the same error messages:

ERROR in : Template parse errors: The pipe 'translate' could not be found ("<ion-header> <ion-toolbar> <ion-title>{{[ERROR ->]'Edit' | translate}}</ion-title> </ion-toolbar> </ion-header>

I can ignore the IDE warnings, although they are annoying. But it would be very nice to be able to use the upcoming Angular compiler.

Thanks in advance, Heiner

[QUESTION] Library-Monorepo problem

Thank you very much for this project, it is very good.

I have a question, how could I use in @ngstack/translate a library, and use that library in an application that also uses @ngstack/translate?

This library can be lazy loaded or it can be loaded normally. I wish it could work for both cases.
Of course, this use case is a common when you use Monorepo in your company.
I also have the need for the library to be publishable, so it should have its own translation

Angular 8 support?

Angular 8 is out there. Is Angular 8 support planned any time soon, or should I create a fork?

Multiple files per language

Is it possible to split a single language translation file into multiple .json files (per module or component)?

Single language file can get really huge for big apps and difficult to maintain.

Setting .json file to be loaded dynamically in routes would be an extra feature.

Wrong version number

Hi,

the version 1.2.2 is not backwards-compatible anymore due to the upgrade to Angular 8.

Attribute directive

Provide the attribute directive support similar to the following:

<div [translate]="key"></div>

Should provide translation into the host element content.

Take browser culture into account

Provide better fallback for browser cultures. For example, when browser is set to zh-CN and translation file is missing, the probing flow should be:

  1. zh-CN.json
  2. zh.json
  3. en.json (or fallback language of choice)

Consider support for explicit support matrix in configuration/code to avoid useless HTTP calls for non-supported cultures.

Improvement suggestions

I've decided to drop my @ngx-translate implementation and turn it into @ngstack/translate implementation. Along the way, I've hit some obstacles, with @ngstack/translate missing some basic features @ngx-translate has. So, I suggest the following improvements:

  1. Translate params should accept numbers, along with strings.
export interface TranslateParams {
    [key: string]: string;
}

should be transformed into:

export interface TranslateParams {
    [key: string]: string | number;
}
  1. get method should translate array of strings, along with string:
get(key: string, params?: TranslateParams, lang?: string): string;

should be transformed into:

get(key: string | string[], params?: TranslateParams, lang?: string): string | string[];

Keep up the good work! :D

How do I extend TranslateService to add local storage support?

To add support for storing/restoring a preferred language into/from local storage, I extended the TranslateService like this:

import { HttpClient } from '@angular/common/http';
import { EventEmitter, Inject, Injectable } from '@angular/core';
import { Settings } from '@app/app.settings';
import { Languages } from '@app/shared/models/language.model';
import { TranslateService, TranslateSettings, TRANSLATE_SETTINGS } from '@ngstack/translate';
import { LocalStorageUtil } from '@shared/helpers/local.storage.util';

@Injectable({
  providedIn: 'root'
})
export class LanguageService extends TranslateService {
  static readonly Language = Settings.Prefix + 'language';

  constructor(http: HttpClient, @Inject(TRANSLATE_SETTINGS) settings: TranslateSettings, private ls: LocalStorageUtil) {
    super(http, settings);
  }

  /**
   * The prefered language to use for the translations.
   */
  get preferedLanguage(): string {
    const defaultLanguage = Languages.find(l => l.default).i18n;
    const language = this.ls.readDecompressed(LanguageService.Language);
    return language || defaultLanguage;
  }

  /**
   * The language to use for the translations.
   */
  get language(): string {
    return this.activeLang;
  }

  /**
   * The language to use for the translations.
   * @param language Language to use for translation
   */
  set language(language: string) {
    this.activeLang = language;
    this.ls.saveCompressed(LanguageService.Language, language);
  }

  /**
   * Raised each time active language gets changed.
   */
  get language$(): EventEmitter<{
    previousValue: string;
    currentValue: string;
  }> {
    return this.activeLangChanged;
  }
}

The core module settings are the following:

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { MatPaginatorIntl, MatSidenavModule } from '@angular/material';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule } from '@angular/router';
import { AppRoutingModule } from '@app/app-routing.module';
import { AvatarModule } from '@app/layout/avatar/avatar.module';
import { MainSidebarContentModule } from '@app/layout/main-sidebar-content/main-sidebar-content.module';
import { TopbarModule } from '@app/layout/topbar/topbar.module';
import { CodemirrorModule } from '@app/shared/components/codemirror/codemirror.module';
import { DataTablePaginatorIntl } from '@app/shared/components/data-table/data-table.paginator';
import { LoaderModule } from '@app/shared/components/loader/loader.module';
import { Languages } from '@app/shared/models/language.model';
import { WildcardRoutingModule } from '@app/wildcard-routing.module';
import { TranslateModule, TranslateService } from '@ngstack/translate';
import 'hammerjs';
import { LoaderInterceptor } from './interceptors/loader.interceptor';
import { TokenInterceptor } from './interceptors/token.interceptor';

// AoT requires an exported function for factories
export function setupTranslateService(service: TranslateService) {
  return () => service.load();
}

@NgModule({
  imports: [
    // Angular modules
    BrowserModule,
    BrowserAnimationsModule,
    RouterModule,
    AppRoutingModule,
    HttpClientModule,

    // Material modules
    MatSidenavModule,

    // Translate module
    TranslateModule.forRoot({
      translationRoot: 'assets/i18n',
      supportedLangs: Languages.map(language => language.i18n),
      activeLang: Languages.find(language => language.default).i18n
    }),

    // Loader module
    LoaderModule,

    // Layout modules
    TopbarModule,
    MainSidebarContentModule,
    AvatarModule,

    // CodeMirror
    CodemirrorModule,

    // WILDCARD ROUTER MUST BE AT LAST POSITION
    WildcardRoutingModule
  ],
  declarations: [],
  entryComponents: [],
  exports: [
    RouterModule,
    HttpClientModule,
    MatSidenavModule,
    LoaderModule,
    TopbarModule,
    MainSidebarContentModule,
    AvatarModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: setupTranslateService,
      deps: [TranslateService],
      multi: true
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptor,
      multi: true
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: LoaderInterceptor,
      multi: true
    },
    { provide: MatPaginatorIntl, useClass: DataTablePaginatorIntl }
  ]
})
export class CoreModule {}

The activeLangChanged event emitter fires on a button click, with activeLang change, but the page doesn't get translated into selected language. Turning on the debugMode, I can see that the active language stays default. Tracking down the network activities, I can see that language files get loaded, but the page remains translated into default language.

Am I missing something here?

Translations default to default language until language file is loaded

I use three languages: en, sr-Latn and hr, with en being the default one.
When I switch to any language other than the default one, the translations are loaded nicely. But, then, when I switch to the third, non-default language, the translations show the default language translations briefly, until the new language file is loaded.

So en => sr-Latn => OK
So en => hr => OK
So en => sr-Latn => hr => Glitch
So en => hr => sr-Latn => Glitch

translate pipe transforming not working

//app.module.ts
import { TranslateModule, TranslateService } from '@ngstack/translate';

export function setupTranslateFactory(service: TranslateService): Function {
    return () => service.load();
}

imports: [
    TranslateModule.forRoot({
        debugMode: true,
        activeLang: 'en'
    })
]

providers: [
{ provide: APP_INITIALIZER, useFactory: setupTranslateFactory, deps: [ TranslateService ], multi: true }
]

// app.component.ts
import { TitleService } from '@ngstack/translate';
export class AppComponent implements OnInit {
    constructor(private titleService: TitleService) {}
    ngOnInit() {
        this.titleService.setTitle('TITLE');
    }
}
//##Document Title is working fine but not in templae LOGIN


{{ 'LOGIN' | translate }}

// package.json
"@angular/core": "^8.2.1"
"@ngstack/translate": "^2.1.0"

TitleService is working, but pipe transforming is not. Just wondering am I missing anything.

HttpInterceptor not triggering with lazy loaded modules

Custom HttpInterceptor not triggering with lazy loaded modules, when using TranslateModule as stated in docs.

It's a complex project, so I cannot show the example code.

The problem with lazy loaded modules and HttpInterceptor is that HttpClientModule can only be imported once in the project inside app.module.ts. Looking into this library's code, I found that HttpClientModule is imported internally, which, I presume, could cause this problem.

The files to look for these imports are:

projects/translate/src/lib/translate.module.ts
projects/translate/src/lib/translate.pipe.spec.ts
projects/translate/src/lib/title.service.spec.ts
projects/translate/src/lib/translate.service.spec.ts

Build for production failed

When build an app for production with ng build --prod, the following error is thrown:

ERROR in Error during template compile of 'AppModule' Function calls are not supported in decorators but 'TranslateModule' was called.

Reason is the forRoot() call in the declaration of the main module.

Allow to specify fallback language

Currently the fallback language is hard coded to "en". In my application I use locales instead of language abbreviation (ex: "en-US").

I'd like to be able to change the fallback language to "en-US" to fallback to when there isn't a match.

Maybe a new config property that can be passed to forRoot()

Something like:

TranslateModule.forRoot({
  activeLang: 'en-US',
  fallbackLang: 'en-US',
  supportedLangs: [
    // ...
  ]
}),

Problem with using parameters

This is my translation file's content:

"AccessDenied": {
  "Title": "Access Denied",
  "Message": "Access is denied to user {name}!"
}

This works:

<div class="page">
    <span class="logo"></span>
    <h1>{{'AccessDenied.Title' | translate}}</h1>
    <p>{{'AccessDenied.Message' | translate:{ 'name': account.name } }}</p>
</div>

This doesn't (no space after param closing curly bracket):

<div class="page">
    <span class="logo"></span>
    <h1>{{'AccessDenied.Title' | translate}}</h1>
    <p>{{'AccessDenied.Message' | translate:{ 'name': account.name }}}</p>
</div>

Error thrown by Angular compiler:

Parser Error: Missing expected } at the end of the expression [{{'AccessDenied.Message' | translate:{ 'name': account.name }}}]

This looks like more like an Angular limitation or a bug.

Also, this should be working to, but currently, it's not (added spaces around param for readability):

"AccessDenied": {
  "Title": "Access Denied",
  "Message": "Access is denied to user { name }!"
}

Result:

Param name is not translated.

I presume that some trimming should be executed when parsing params.

Also, when passing param object, single quoting the param name is not necessary, as we are passing an object.

So, this:

<p>{{'AccessDenied.Message' | translate:{ 'name': account.name } }}</p>

can be written like this (no quotes):

<p>{{'AccessDenied.Message' | translate:{ name: account.name } }}</p>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.