Top Related Projects
i18next: learn once - translate everywhere
:globe_with_meridians: Internationalization plugin for Vue.js
The monorepo home to all of the FormatJS related libraries, most notably react-intl.
Give your JavaScript the ability to speak many languages.
🌍 📖 A readable, automated, and optimized (3 kb) internationalization for JavaScript
Quick Overview
ngx-translate/core is an internationalization (i18n) library for Angular applications. It provides a simple way to manage translations in your Angular projects, allowing for easy language switching and dynamic content localization.
Pros
- Easy integration with Angular projects
- Supports multiple file formats for translations (JSON, YAML, etc.)
- Allows for dynamic language switching at runtime
- Provides a pipe for easy translation in templates
Cons
- Limited built-in features compared to some other i18n solutions
- Requires manual management of translation files
- May have performance issues with large translation sets
- Lacks advanced pluralization support out of the box
Code Examples
- Basic translation usage in a component:
import { TranslateService } from '@ngx-translate/core';
export class MyComponent {
constructor(private translate: TranslateService) {
translate.setDefaultLang('en');
translate.use('en');
}
switchLanguage(lang: string) {
this.translate.use(lang);
}
}
- Using the translate pipe in a template:
<h1>{{ 'HELLO_WORLD' | translate }}</h1>
<p>{{ 'WELCOME_MESSAGE' | translate:{ name: username } }}</p>
- Programmatically getting translations:
this.translate.get('SOME_KEY').subscribe((res: string) => {
console.log(res);
});
this.translate.get(['KEY1', 'KEY2']).subscribe((res: any) => {
console.log(res.KEY1, res.KEY2);
});
Getting Started
-
Install the package:
npm install @ngx-translate/core @ngx-translate/http-loader
-
Import the TranslateModule in your app.module.ts:
import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { HttpClient, HttpClientModule } from '@angular/common/http'; export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http); } @NgModule({ imports: [ HttpClientModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } }) ], // ... }) export class AppModule { }
-
Create translation files (e.g., en.json, fr.json) in your assets folder.
-
Use the TranslateService in your components and the translate pipe in your templates.
Competitor Comparisons
i18next: learn once - translate everywhere
Pros of i18next
- Framework-agnostic, can be used with various JavaScript frameworks
- Extensive plugin ecosystem for additional functionality
- Supports pluralization and context-based translations
Cons of i18next
- Steeper learning curve due to more complex API
- Requires additional setup for framework-specific integrations
Code Comparison
i18next:
import i18next from 'i18next';
i18next.init({
lng: 'en',
resources: {
en: {
translation: {
key: 'Hello, {{name}}!'
}
}
}
});
i18next.t('key', { name: 'John' });
ngx-translate/core:
import { TranslateService } from '@ngx-translate/core';
constructor(private translate: TranslateService) {
translate.setDefaultLang('en');
translate.use('en');
}
this.translate.get('key', { name: 'John' }).subscribe((res: string) => {
console.log(res);
});
Both libraries offer robust internationalization solutions, but i18next provides more flexibility across different frameworks, while ngx-translate/core is specifically tailored for Angular applications. i18next's extensive plugin system allows for more customization, but it may require additional setup. ngx-translate/core integrates more seamlessly with Angular's ecosystem, offering a simpler API for basic use cases.
:globe_with_meridians: Internationalization plugin for Vue.js
Pros of vue-i18n
- Designed specifically for Vue.js, offering seamless integration and better performance
- Supports pluralization and date/time localization out of the box
- Provides a more flexible interpolation syntax, allowing for complex translations
Cons of vue-i18n
- Limited to Vue.js applications, whereas ngx-translate/core is framework-agnostic
- Slightly steeper learning curve for developers new to Vue.js ecosystem
- Less extensive third-party plugin ecosystem compared to ngx-translate/core
Code Comparison
vue-i18n:
const i18n = new VueI18n({
locale: 'en',
messages: {
en: { hello: 'Hello {name}!' },
fr: { hello: 'Bonjour {name}!' }
}
})
ngx-translate/core:
this.translate.setTranslation('en', {
hello: 'Hello {{name}}!'
});
this.translate.setTranslation('fr', {
hello: 'Bonjour {{name}}!'
});
Both libraries offer similar functionality for basic translations, but vue-i18n's syntax is more concise and Vue-specific. ngx-translate/core uses a service-based approach, which is more aligned with Angular's dependency injection system.
The monorepo home to all of the FormatJS related libraries, most notably react-intl.
Pros of formatjs
- Broader ecosystem support, including React, Vue, and vanilla JavaScript
- More comprehensive internationalization features, including pluralization and gender-aware formatting
- Active development with frequent updates and improvements
Cons of formatjs
- Steeper learning curve due to more complex API and features
- Larger bundle size, which may impact performance in smaller applications
- Requires more setup and configuration compared to ngx-translate/core
Code Comparison
ngx-translate/core:
import { TranslateService } from '@ngx-translate/core';
constructor(private translate: TranslateService) {
translate.setDefaultLang('en');
}
this.translate.get('HELLO').subscribe((res: string) => {
console.log(res);
});
formatjs:
import { IntlProvider, FormattedMessage } from 'react-intl';
<IntlProvider messages={messages} locale={locale}>
<FormattedMessage
id="greeting"
defaultMessage="Hello, {name}!"
values={{ name: 'World' }}
/>
</IntlProvider>
Both libraries offer internationalization solutions, but formatjs provides a more comprehensive set of features at the cost of increased complexity. ngx-translate/core is simpler and more lightweight, making it a good choice for Angular-specific projects with basic translation needs. formatjs is better suited for larger applications or those requiring advanced internationalization features across multiple frameworks.
Give your JavaScript the ability to speak many languages.
Pros of Polyglot.js
- Lightweight and simple to use, with no external dependencies
- Supports pluralization and interpolation out of the box
- Can be used in both browser and Node.js environments
Cons of Polyglot.js
- Limited features compared to more comprehensive solutions
- Lacks built-in support for lazy loading or dynamic translation updates
- No specific Angular integration, requiring additional setup for Angular projects
Code Comparison
Polyglot.js:
import Polyglot from 'node-polyglot';
const polyglot = new Polyglot();
polyglot.extend({"hello": "Hello, %{name}!"});
console.log(polyglot.t("hello", {name: "world"}));
ngx-translate/core:
import { TranslateService } from '@ngx-translate/core';
constructor(private translate: TranslateService) {
translate.setTranslation('en', {"hello": "Hello, {{name}}!"});
console.log(translate.instant("hello", {name: "world"}));
}
Both libraries provide similar functionality for basic translation needs. Polyglot.js offers a more straightforward setup for non-Angular projects, while ngx-translate/core is specifically designed for Angular applications, providing seamless integration with Angular's ecosystem and additional features like lazy loading and dynamic language switching.
🌍 📖 A readable, automated, and optimized (3 kb) internationalization for JavaScript
Pros of js-lingui
- Supports multiple frameworks (React, Vue, Angular) while ngx-translate is Angular-specific
- Offers advanced pluralization and formatting features
- Provides a command-line interface for managing translations
Cons of js-lingui
- Steeper learning curve compared to ngx-translate's simpler API
- Requires additional setup and configuration
- May have a larger bundle size due to its comprehensive feature set
Code Comparison
ngx-translate/core:
import { TranslateService } from '@ngx-translate/core';
constructor(private translate: TranslateService) {
translate.setDefaultLang('en');
}
this.translate.get('HELLO').subscribe((res: string) => {
console.log(res);
});
js-lingui:
import { Trans } from '@lingui/macro';
function MyComponent() {
return <Trans>Hello, World!</Trans>;
}
// In a separate messages.po file:
msgid "Hello, World!"
msgstr "Bonjour, le monde !"
Both libraries offer straightforward ways to handle translations, but js-lingui's approach is more declarative and integrates well with build processes. ngx-translate uses a service-based approach, which may be more familiar to Angular developers.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
@ngx-translate/core
The internationalization (i18n) library for Angular.
Simple example using ngx-translate: https://stackblitz.com/github/ngx-translate/example
Get the complete changelog here: https://github.com/ngx-translate/core/releases
Table of Contents
Installation
First you need to install the npm module:
npm install @ngx-translate/core --save
Choose the version corresponding to your Angular version:
Angular | @ngx-translate/core | @ngx-translate/http-loader |
---|---|---|
16+ | 15.x+ | 8.x+ |
13+ (ivy only) | 14.x+ | 7.x+ |
10/11/12/13 | 13.x+ | 6.x+ |
9 | 12.x+ | 5.x+ |
8 | 12.x+ | 4.x+ |
7 | 11.x+ | 4.x+ |
6 | 10.x | 3.x |
5 | 8.x to 9.x | 1.x to 2.x |
4.3 | 7.x or less | 1.x to 2.x |
2 to 4.2.x | 7.x or less | 0.x |
Usage
1. Import the TranslateModule
:
Finally, you can use ngx-translate in your Angular project. You have to import TranslateModule.forRoot()
in the root NgModule of your application.
The forRoot
static method is a convention that provides and configures services at the same time.
Make sure you only call this method in the root module of your application, most of the time called AppModule
.
This method allows you to configure the TranslateModule
by specifying a loader, a parser and/or a missing translations handler.
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core';
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot()
],
bootstrap: [AppComponent]
})
export class AppModule { }
SharedModule
If you use a SharedModule
that you import in multiple other feature modules,
you can export the TranslateModule
to make sure you don't have to import it in every module.
@NgModule({
exports: [
CommonModule,
TranslateModule
]
})
export class SharedModule { }
Note: Never call a
forRoot
static method in theSharedModule
. You might end up with different instances of the service in your injector tree. But you can useforChild
if necessary.
Lazy loaded modules
When you lazy load a module, you should use the forChild
static method to import the TranslateModule
.
Since lazy loaded modules use a different injector from the rest of your application, you can configure them separately with a different loader/compiler/parser/missing translations handler.
To make a child module extend translations from parent modules use extend: true
. This will cause the service to also
use translations from its parent module.
You can also isolate the service by using isolate: true
. In which case the service is a completely isolated instance (for translations, current lang, events, ...).
Otherwise, by default, it will share its data with other instances of the service (but you can still use a different loader/compiler/parser/handler even if you don't isolate the service).
@NgModule({
imports: [
TranslateModule.forChild({
loader: {provide: TranslateLoader, useClass: CustomLoader},
compiler: {provide: TranslateCompiler, useClass: CustomCompiler},
parser: {provide: TranslateParser, useClass: CustomParser},
missingTranslationHandler: {provide: MissingTranslationHandler, useClass: CustomHandler},
isolate: true
})
]
})
export class LazyLoadedModule { }
Configuration
By default, there is no loader available. You can add translations manually using setTranslation
but it is better to use a loader.
You can write your own loader, or import an existing one.
For example you can use the TranslateHttpLoader
that will load translations from files using HttpClient.
To use it, you need to install the http-loader package from @ngx-translate:
npm install @ngx-translate/http-loader --save
Once you've decided which loader to use, you have to setup the TranslateModule
to use it.
Here is how you would use the TranslateHttpLoader
to load translations from "/assets/i18n/[lang].json" ([lang]
is the lang that you're using, for english it could be en
):
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {AppComponent} from './app';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
AoT
If you want to configure a custom TranslateLoader
while using AoT compilation or Ionic, you must use an exported function instead of an inline function.
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
2. Define the default language
for the application
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot({
defaultLanguage: 'en'
})
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
3. Init the TranslateService
for your application:
import {Component} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
@Component({
selector: 'app',
template: `
<div>{{ 'HELLO' | translate:param }}</div>
`
})
export class AppComponent {
param = {value: 'world'};
constructor(translate: TranslateService) {
// this language will be used as a fallback when a translation isn't found in the current language
translate.setDefaultLang('en');
// the lang to use, if the lang isn't available, it will use the current loader to get them
translate.use('en');
}
}
4. Define the translations:
Once you've imported the TranslateModule
, you can put your translations in a json file that will be imported with the TranslateHttpLoader
. The following translations should be stored in en.json
.
{
"HELLO": "hello {{value}}"
}
You can also define your translations manually with setTranslation
.
translate.setTranslation('en', {
HELLO: 'hello {{value}}'
});
The TranslateParser
understands nested JSON objects. This means that you can have a translation that looks like this:
{
"HOME": {
"HELLO": "hello {{value}}"
}
}
You can then access the value by using the dot notation, in this case HOME.HELLO
.
5. Use the service, the pipe or the directive:
You can either use the TranslateService
, the TranslatePipe
or the TranslateDirective
to get your translation values.
With the service, it looks like this:
translate.get('HELLO', {value: 'world'}).subscribe((res: string) => {
console.log(res);
//=> 'hello world'
});
This is how you do it with the pipe:
<div>{{ 'HELLO' | translate:param }}</div>
And in your component define param
like this:
param = {value: 'world'};
You can construct the translation keys dynamically by using simple string concatenation inside the template:
<ul *ngFor="let language of languages">
<li>{{ 'LANGUAGES.' + language | translate }}</li>
</ul>
Where languages
is an array member of your component:
languages = ['EN', 'FR', 'BG'];
You can also use the output of the built-in pipes uppercase
and lowercase
in order to guarantee that your dynamically generated translation keys are either all uppercase or all lowercase. For example:
<p>{{ 'ROLES.' + role | uppercase | translate }}</p>
role = 'admin';
will match the following translation:
{
"ROLES": {
"ADMIN": "Administrator"
}
}
This is how you use the directive:
<div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div>
Or even simpler using the content of your element as a key:
<div translate [translateParams]="{value: 'world'}">HELLO</div>
6. Use HTML tags:
You can easily use raw HTML tags within your translations.
{
"HELLO": "Welcome to my Angular application!<br><strong>This is an amazing app which uses the latest technologies!</strong>"
}
To render them, simply use the innerHTML
attribute with the pipe on any element.
<div [innerHTML]="'HELLO' | translate"></div>
API
TranslateService
Properties:
-
currentLang
: The lang currently used -
currentLoader
: An instance of the loader currently used (static loader by default) -
onLangChange
: An EventEmitter to listen to lang change events. ALangChangeEvent
is an object with the propertieslang: string
&translations: any
(an object containing your translations).example:
onLangChange.subscribe((event: LangChangeEvent) => { // do something });
-
onTranslationChange
: An EventEmitter to listen to translation change events. ATranslationChangeEvent
is an object with the propertieslang: string
&translations: any
(an object containing your translations).example:
onTranslationChange.subscribe((event: TranslationChangeEvent) => { // do something });
-
onDefaultLangChange
: An EventEmitter to listen to default lang change events. ADefaultLangChangeEvent
is an object with the propertieslang: string
&translations: any
(an object containing your translations).example:
onDefaultLangChange.subscribe((event: DefaultLangChangeEvent) => { // do something });
Methods:
setDefaultLang(lang: string)
: Sets the default language to use as a fallbackgetDefaultLang(): string
: Gets the default languageuse(lang: string): Observable<any>
: Changes the lang currently usedgetTranslation(lang: string): Observable<any>
: Gets an object of translations for a given language with the current loadersetTranslation(lang: string, translations: Object, shouldMerge: boolean = false)
: Manually sets an object of translations for a given language, setshouldMerge
to true if you want to append the translations instead of replacing themaddLangs(langs: Array<string>)
: Add new langs to the listgetLangs()
: Returns an array of currently available langsget(key: string|Array<string>, interpolateParams?: Object): Observable<string|Object>
: Gets the translated value of a key (or an array of keys) or the key if the value was not foundgetStreamOnTranslationChange(key: string|Array<string>, interpolateParams?: Object): Observable<string|Object>
: Returns a stream of translated values of a key (or an array of keys) or the key if the value was not found. Without anyonTranslationChange
events this returns the same value asget
but it will also emit new values whenever the translation changes.stream(key: string|Array<string>, interpolateParams?: Object): Observable<string|Object>
: Returns a stream of translated values of a key (or an array of keys) or the key if the value was not found. Without anyonLangChange
events this returns the same value asget
but it will also emit new values whenever the used language changes.instant(key: string|Array<string>, interpolateParams?: Object): string|Object
: Gets the instant translated value of a key (or an array of keys). /!\ This method is synchronous and the default file loader is asynchronous. You are responsible for knowing when your translations have been loaded and it is safe to use this method. If you are not sure then you should use theget
method instead.set(key: string, value: string, lang?: string)
: Sets the translated value of a keyreloadLang(lang: string): Observable<string|Object>
: Calls resetLang and retrieves the translations object for the current loaderresetLang(lang: string)
: Removes the current translations for this lang. /!\ You will have to calluse
,reloadLang
orgetTranslation
again to be able to get translationsgetBrowserLang(): string | undefined
: Returns the current browser lang if available, or undefined otherwisegetBrowserCultureLang(): string | undefined
: Returns the current browser culture language name (e.g. "de-DE" if available, or undefined otherwise
Write & use your own loader
If you want to write your own loader, you need to create a class that implements TranslateLoader
. The only required method is getTranslation
that must return an Observable
. If your loader is synchronous, just use Observable.of
to create an observable from your static value.
Example
class CustomLoader implements TranslateLoader {
getTranslation(lang: string): Observable<any> {
return Observable.of({KEY: 'value'});
}
}
Once you've defined your loader, you can provide it in your configuration by adding it to its providers
property.
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot({
loader: {provide: TranslateLoader, useClass: CustomLoader}
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
Another custom loader example with translations stored in Firebase
How to use a compiler to preprocess translation values
By default, translation values are added "as-is". You can configure a compiler
that implements TranslateCompiler
to pre-process translation values when they are added (either manually or by a loader). A compiler has the following methods:
compile(value: string, lang: string): string | Function
: Compiles a string to a function or another string.compileTranslations(translations: any, lang: string): any
: Compiles a (possibly nested) object of translation values to a structurally identical object of compiled translation values.
Using a compiler opens the door for powerful pre-processing of translation values. As long as the compiler outputs a compatible interpolation string or an interpolation function, arbitrary input syntax can be supported.
How to handle missing translations
You can setup a provider for the MissingTranslationHandler
in the bootstrap of your application (recommended), or in the providers
property of a component. It will be called when the requested translation is not available. The only required method is handle
where you can do whatever you want. If this method returns a value or an observable (that should return a string), then this will be used. Just don't forget that it will be called synchronously from the instant
method.
You can use useDefaultLang
to decide whether default language string should be used when there is a missing translation in current language. Default value is true. If you set it to false, MissingTranslationHandler
will be used instead of the default language string.
Example:
Create a Missing Translation Handler
import {MissingTranslationHandler, MissingTranslationHandlerParams} from '@ngx-translate/core';
export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) {
return 'some value';
}
}
Setup the Missing Translation Handler in your module import by adding it to the forRoot
(or forChild
) configuration.
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot({
missingTranslationHandler: {provide: MissingTranslationHandler, useClass: MyMissingTranslationHandler},
useDefaultLang: false
})
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
Parser
If you need it for some reason, you can use the TranslateParser
service.
Methods:
-
interpolate(expr: string | Function, params?: any): string
: Interpolates a string to replace parameters or calls the interpolation function with the parameters.This is a {{ key }}
==>This is a value
withparams = { key: "value" }
(params) => \
This is a ${params.key}` ==>This is a value
withparams = { key: "value" }
-
getValue(target: any, key: string): any
: Gets a value from an object by composed keyparser.getValue({ key1: { keyA: 'valueI' }}, 'key1.keyA') ==> 'valueI'
FAQ
I'm getting an error npm ERR! peerinvalid Peer [...]
If you're using npm 2.x, upgrade to npm 3.x, because npm 2 doesn't handle peer dependencies well. With npm 2 you could only use fixed versions, but with npm 3 you can use ^
to use a newer version if available.
If you're already on npm 3, check if it's an error (npm ERR!
) or a warning (npm WARN!
), warning are just informative and if everything works then don't worry !
If you're using an old version of Angular and ngx-translate requires a newer version then you should consider upgrading your application to use the newer angular 2 version. There is always a reason when I upgrade the minimum dependencies of the library. Often it is because Angular had a breaking changes. If it's not an option for you, then check the changelog to know which version is the last compatible version for you.
I want to hot reload the translations in my application but reloadLang
does not work
If you want to reload the translations and see the update on all your components without reloading the page, you have to load the translations manually and call setTranslation
function which triggers onTranslationChange
.
Plugins
- Localize Router by @meeroslav: An implementation of routes localization for Angular. If you need localized urls (for example /fr/page and /en/page).
- .po files Loader by @biesbjerg: Use .po translation files with ngx-translate
- browser.i18n Loader by @pearnaly: loader for native translation files of browser extensions.
- ngx-translate-extract by @biesbjerg: Extract translatable strings from your projects
- MessageFormat Compiler by @lephyrus: Compiler for ngx-translate that uses messageformat.js to compile translations using ICU syntax for handling pluralization, gender, and more
- ngx-translate-zombies by @seveves: A vscode extension that finds unused translation keys and shows them in a diff view (so called zombies).
- ngx-translate-multi-http-loader by @denniske: Fetch multiple translation files with ngx-translate.
- ngx-translate-cache by @jgpacheco: Simplified version of localize-router. If you are already using localize-router you don't need this extension. This extension is aimed only to facilitate language caching.
- ngx-translate-module-loader by @larscom: Fetch multiple translation files (http) with ngx-translate. Each translation file gets it's own namespace out of the box and the configuration is very flexible.
- ngx-translate-all by @irustm: Automate translations for Angular projects.
- ngx-translate-migrate by @irustm: Automate migrations from ngx-translate to Angular i18n.
- ngx-translate-lint by @svoboda-rabstvo: Simple CLI tools for check ngx-translate keys in whole app
- ngx-translate-cut by @bartholomej: Simple and useful pipe for cutting translations âï¸
Editors
- BabelEdit â translation editor for JSON files
- Translation Manager â Progressive web-app, translation editor for JSON files
- Crowdl.io â Free translation management and crowd-translations tool with support for JSON files
- ngx-translate-editor - Simple GUI for CRUD translate files of
ngx-translate
, which includedngx-translate-lint
- tl8.io - A multi-platform application to enable the whole product team, including non-developers, to modify translations. WYSIWYG interface. Results can be downloaded as JSON and copied in the project as is.
Extensions
VScode
- Generate Translation by @thiagocordeirooo: A visual studio code extension for you to generate the translations without leaving the current file.
- Lingua by @chr33z: A visual studio code extension to help managing translations for ngx-translate - featuring inline translation lookup and in-place translation creation and editing.
Additional Framework Support
Top Related Projects
i18next: learn once - translate everywhere
:globe_with_meridians: Internationalization plugin for Vue.js
The monorepo home to all of the FormatJS related libraries, most notably react-intl.
Give your JavaScript the ability to speak many languages.
🌍 📖 A readable, automated, and optimized (3 kb) internationalization for JavaScript
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot