Giter VIP home page Giter VIP logo

ng-i18next's Introduction

ng-i18next - use i18next with AngularJS Build Status

Project goal is to provide an easy way to use i18next with AngularJS 1.x:

  • ng-i18next directive
  • i18next filter

First check out the documentation by Jan Mühlemann.

Features

  • AngularJS provider, directive and filter
  • variable binding (translates again when variable changes)
  • nested translations ($t('hello'); see i18next documentation)
  • scope variables in translations (if the translation contains directives of variables like {{hello}}, they'll get compiled)
  • sprintf support (directive and provider)

Installation Bower

You can install ng-i18next as a bower dependency:

bower install ng-i18next

Installation npm

You can install ng-i18next as a npm dependency:

npm install ng-i18next

Upgrading from <=0.5.5

You will need to

  1. Move initialization of i18next from the ng-i18next provider within Angular to i18next natively before booting Angular
  2. Change translations using the $i18next provider in you Angular code. From $i18next('localeKey') to $i18next.t('localeKey')

Usage

First add

to your HTML file. AngularJS, ngSanitize, i18next, and i18next-xhr-backend have to be loaded before ng-i18next!

Before booting angular use i18next configuration system to configure and load your localization resources. Refer to i18next configuration reference.

window.i18next
	.use(window.i18nextXHRBackend);

window.i18next.init({
	debug: true,
	lng: 'de', // If not given, i18n will detect the browser language.
	fallbackLng: 'dev', // Default is dev
	backend: {
		loadPath: '../locales/{{lng}}/{{ns}}.json'
	},
	useCookie: false,
	useLocalStorage: false
}, function (err, t) {
	console.log('resources loaded');
});

There are three ways to use ng-i18next:

filter

<p>{{'hello' | i18next}}</p>

=> translates hello

<p>{{hello | i18next}}</p>

=> translates $scope.hello

directive

Basics

<p ng-i18next="hello"></p>

=> translates hello

<p ng-i18next="{{hello}}"></p>

=> translates $scope.hello

<p ng-i18next>hello</p>

=> translates hello (uses the content of the p-tag)

<p ng-i18next>{{hello}}</p>

=> translates $scope.hello (uses the content of the p-tag)

Note, that HTML isn't compiled!

HTML

<p ng-i18next="[html]hello"></p>

=> translates hello and compiles HTML

<p ng-i18next="[html]{{hello}}"></p>

=> translates $scope.hello and compiles HTML

Attributes

<a href="#" ng-i18next="[title]hello">This is a link.</a>

=> translates hello and sets it as the title

<a href="#" ng-i18next="[title]{{hello}}">This is a link.</a>

=> translates $scope.hello and sets it as the title

You can combine both, too!

Attributes + text content

<a href="#" ng-i18next="[title]hello;content"></a>

=> translates hello and sets it as the title => translates content and sets it as the text of the link.

<a href="#" ng-i18next="[title]{{hello}};{{content}}"></a>

=> translates $scope.hello and sets it as the title => translates $scope.content and sets it as the text of the link.

Attributes + HTML content

<a href="#" ng-i18next="[title]hello;[html]content"></a>

=> translates hello and sets it as the title => translates content and compiles the HTML as the content of the link.

<a href="#" ng-i18next="[title]{{hello}};[html]{{content}}"></a>

=> translates $scope.hello and sets it as the title => translates $scope.content and compiles the HTML as the content of the link.

Passing Options

You can also pass options:

<p ng-i18next="[i18next]({lng:'de'})hello"></p>

=> translates hello in German (de)

Passing Options + HTML

Also options work perfectly together with html:

<p ng-i18next="[html:i18next]({lng:'de'})hello"></p>

=> translates hello in German (de) and compiles it to HTML code.

Passing Options - sprintf

You can use i18next sprintf feature:

<p ng-i18next="[i18next]({sprintf:['a','b','c','d']})sprintfString">

where sprintfString could be The first 4 letters of the english alphabet are: %s, %s, %s and %s in your translation file.

Using the directive, postProcess:'sprintf' isn't neccassary. The directive will add it automatically when using sprintf in the options.

provider

=> translates hello

angular
	.module('MyApp', ['jm.i18next'])
	.controller('MyProviderCtrl', function ($scope, $i18next) {
		'use strict';
		$scope.hello = $i18next.t('hello');
});

=> translates hello with translate options

$scope.sprintf = $i18next.t('both.sprintf', { postProcess: 'sprintf', sprintf: ['a', 'b', 'c', 'd'] });

=> translates copyright label and use interpolation to add the year

locale

{
    "copyrightLabel": "Copyright __year__ Acme, Inc. All rights reserved",
}

JavaScript

$i18next.t('copyrightLabel', { year: this.$window.moment().year() });

Results

Copyright 2016 Acme, Inc. All rights reserved


For more, see examples.

There are two ways to run the examples:

gulp serve

Run this inside your ng-i18next directory. (This requires you to have NodeJS and gulp to be installed.)


Contribute

To contribute, you must have:

installed.

Load all dependencies using npm, bower and typings:

npm install
bower install
typings install

Build ng-i18next.js using Gulp:

gulp build

Test ng-i18next.js using Gulp:

gulp test

Examples

You can run the examples using:

gulp serve

(note that you have to be in the root directory of this project)

Do not just open the HTML files. That won't work.


Supported browsers

ng-i18next is tested with these browsers:

  • latest Firefox
  • latest Chrome
  • IE9 and above

IE8 isn't supported. ng-i18next should work with every browser that is supported by AngularJS.

However, last time we checked, just adding polyfills do the job on IE8.


Changelog

For changelog file please see CHANGELOG.md


License

MIT License

ng-i18next's People

Contributors

anwalkers avatar awk avatar bolasblack avatar bugwelle avatar dependabot[bot] avatar efolio avatar holgerde avatar jamuhl avatar julien51 avatar justinsa avatar lcalvy avatar masterpoi avatar medialwerk avatar nsand avatar osharper avatar putermancer avatar qraynaud avatar vbardales avatar venables avatar wardme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ng-i18next's Issues

Changing language after app initialization

I'm trying to integrate ng-i18next into my app and I have hit a problem: I can not change the language from within a controller. I want to allow my user to click on the language code and change the UI language based on that action.
I'm using the directive based approach.
Is such a functionality possible?

Incompatibility with ng-class

Hello,

Maybe I'm using the directive wrong, but simple example:

<a ng-class="{'someclass': $first}" ng-i18next="panel.id" ng-repeat="panel in panels"></a>

This doesn't apply "someclass". Simply removing the ng-i18next attribute fixes it.
Right now I'm doing this as a workaround:

<a ng-class="{'someclass': $first}" title="{{panel.id | i18next}}" ng-repeat="panel in panels"></a>

Usage with angular and browserify

I am a bit confused,

i18next website tells me do install "i18next-client" instead of "i18next" to use with browserify.

Which version should I use ?

I am interested to use your code, but I can't install it with npm, is there a way to get this work in a later released ?

noConflict mode? - i18next: conflict with Google`s libphonenumber

I`ve tried to add it to my project and got:

TypeError: undefined is not a function
    at init (public_html/deps/ng-i18next/dist/ng-i18next.js:35:17)
    at optionsChange (public_html/deps/ng-i18next/dist/ng-i18next.js:72:4)
    at self.$get (public_html/deps/ng-i18next/dist/ng-i18next.js:131:4)
    at Object.invoke (public_html/deps/angular/angular.js:4182:17)
    at http://localhost:8383/site/deps/angular/angular.js:4000:37
    at getService (public_html/deps/angular/angular.js:4141:39)
    at Object.invoke (public_html/deps/angular/angular.js:4173:13)
    at http://localhost:8383/site/deps/angular/angular.js:6482:43
    at forEach (public_html/deps/angular/angular.js:323:20)
    at Object.<anonymous> (public_html/deps/angular/angular.js:6480:13) (23:10:12:875 | error)

My code is:

 .config(function ($routeProvider, $i18nextProvider) {
            $i18nextProvider.options = {
                lng: 'ru',
                useCookie: false,
                useLocalStorage: false,
                fallbackLng: 'en',
                resGetPath: '../../resources/i18n/__lng__/__ns__.json'
            };

Called it like:

  <p ng-i18next="mainTitle"></p>

json

{
    "mainTitle": "Fix Your Ride!"
}

What I`ve missed?

if $i18nextProvider.options include `ns`, $i18next will not work.

For example, I have two namespace file: messages.json and options.json.

The i18next option will be like this:

var i18nOpt = {
  useLocalStorage: false,
  fallbackLng: 'dev',
  resGetPath: 'locales/__lng__/__ns__.json',
  ns: {
    namespaces: ['messages', 'option'],
    defaultNs: 'messages'
  }
}

if I run code $.t('header'), it's all right.

if I run code $.t('header', i18nOpt), the function will return hearder.

I find the code in file provider.js#L58 will do the same thing.

Maybe I can fix it tomorrow.

Take into account [html]key.path

i18next allows for more complex values for ng-i18n such as [html]key.path which will proceed to an injection of unescaped HTML rather than escaped as text.
It also allows for [attr]key.path to setup an attribute's value rather than the content. (this is may be useful for title on links or alt on images).

Both filter and directive flash Key in DOM before replacing it with translated Value

Is there a way to prevent the i18next key from being displayed on-screen for a second before it's replaced with its corresponding value?

For example, I tried using both the filter and the directive in the header of my layout:

{
    "app_name" : "App Name"
}
<a class="navbar-brand" href="#/">{{ "app_name" | i18next }}</a>
<a class="navbar-brand" href="#/" ng-i18next="app_name"></a>

Regardless of which of those I use, when I reload my page "app_name" appears for a split second before i18next does its magic and replaces it with the properly translated "App Name". Is there something else I need to do to prevent this from happening?

add more examples

Add more examples like

  • changing i18next options
  • changing scope
  • ...

minified version does not work

Even if we're using ngmin to minimize ng-i18next, it doesn't look for .$get in the provider, so uglifyJS replaces $rootScope with another name (e.g. e).

Add documentation on dynamic locale change

Hi, first of this is awesome project! thank you so much!

I'm currently trying to implement the dynamic language change, please may you let me know if that is possible at all?

My main.js.coffee looks like the following:

locale = "en"

angular.module("jm.i18next").config [
  "$i18nextProvider"
  ($i18nextProvider) ->
    $i18nextProvider.options =
      interpolationPrefix: '%{'
      interpolationSuffix: '}'      
      lng: locale
      # useCookie: false
      # useLocalStorage: false
      # fallbackLng: "en"
      resGetPath: '/locales/%{lng}.json'
      # useLocalStorage: true      
      # localStorageExpirationTime: 60
]

@app = angular.module('homekit', ['templates', 'ngRoute', 'ngResource', "jm.i18next"])

the question is - if it is possible to change the locale of the application from within the angular controller ?

i18next interpolation service

Hey @archer96, looks like you build angular-translate's little brother :)

I'll release version 1.0 very soonish and with the release of 1.0 I introduce pluggable interpolation services. About about building an interpolation service extension for i18next?

Sprintf also for filters

It would be great if you could pass sprintf parameters also to the i18next filter.

I am thinking of a similar implementation as in angular-translate. Here you transmitted to the filter parameters as follows:

{{ 'TRANSLATION_ID' | translate:'{ username: "PascalPrecht" }' }}

Such an implementation in ng-i18next would be very helpful for my current project. Thank you in advance!

ng-i18next cloak

When you reload a page quickly, you can sometimes see the placeholder translation keys before the language file has had a chance to load.

I'd recommend a directive similar to ng-cloak to allow the page, or elements on it, to stay hidden until translations have loaded.

ng-model not working when using ng-i18next

In an app I have a textarea in which I paste or type some content. This content is bound to the model. To make this visible I have a second textarea which shows this content. As soon as I use directive ng-i18next on the first textarea, the content I type in the first textarea is not bound to the model and is not showing up in second textarea!

<textarea id="pasteArea" ng-i18next="[title]Paste-your-excel-here" ng-model="pastedRawExcel" /> <textarea>{{pastedRawExcel}}</textarea>

using inside a service

Hi

we are trying to use this module in a service, but the service/filter is not initialized fully

//simplified example
angular.module('ModuleName').service("AwesomeService", ['$i18next',
function pollingTimer($i18next) {
function ctor() {
var test = $i18next('gender.male'); //not initialized
}
ctor();
}]);

once it has loaded the translations it would work, but at this point it is too late

do you know how to inject this into a service correctly? or if it can be done?

thanks

evalAsync in unit tests not executed - tests not actually run!

In making a change to the directive I wanted to update the unit tests.

I wrote a new test following the current pattern (using evalAsync) and even though the test was clearly going to fail (TDD :-) it passed! I deliberately broke an existing test and it too still passed.

It looks like the function passed to evalAsync is never actually executed during the tests - and since that's where the expect() call is - it never fails.

Adding a $rootScope.$apply() causes the function passed to evalAsync to pass - however that leads to more indications that this code is dead - the functions all call 'done();' - however that function is not in scope.

Is 'done()' supposed to be the method from Jasmine 2.0 ? It looks like the project is still using Jasmine 1.3.x ? (and anyways in jasmine 2.0 done is passed in as an argument to it() etc)

How to use a preloaded translation file

I run a build process which packages all app files into one .js file, which could include the default translation file. How do I provide this to ng-i18next so that it doesn't try to fetch it from the server?

Filtered expression update when loading locale files

Hello,

I'm having a small issue with the i18next filter.
The provider is configured this way:

$i18nextProvider.options = {
  lng: 'en',
  useCookie: false,
  useLocalStorage: false,
  fallbackLng: 'en',
  resGetPath: 'locales/__lng__.json'
};

And the HTML is a simple:

<div ng-18next="testkey"></div>
<div>{{'testkey' | i18next}}</div>

The second div's content becomes testkey instead of the expected text associated with the key.

Apparently the div's content doesn't get refreshed once the json file is loaded, while the div with the ng-i18next attribute gets updated properly.

To make sure I simply set useLocalStorage to true. Once the json file was cached, the text appeared properly in the second div..

Any idea what the issue could be? The page is pretty much empty and there is no JS except for the ng-i18next initialization...

pluralization problem

We have problems, maybe because of a missing understanding, to get a correct translations for a given pluralization case (see below). We expect to
get :
"Wochenende!!!!"
for the html:
<p>{{'days.rest' | i18next:{count:0} }}</p>,
but we get always:
"Noch 0 Tage bis zum Wochenende!".

Does anybody has a hint whats wrong with our code?
Thanx

Lutz

We use the following translation resources:

//DE
"days":{
"rest": "Noch count Tag bis zum Wochenende.",
"rest_plural": "Noch count Tage bis zum Wochenende!",
"rest_plural_0": "Wochenende!!!!"
},
//EN
"days":{
"rest": "Still count day until weekend.",
"rest_plural": "Still count days until weekend!",
"rest_plural_0": "Weekend, work is out!!!!"
},

and within the .../filter/passingOptions.html

    <p>{{'days.rest' | i18next:{count:0} }}</p>
    <p>{{'days.rest' | i18next:{count:1} }}</p>
    <p>{{'days.rest' | i18next:{count:4} }}</p>

Can't translate when controller is on html element

I've got a controller called SiteCtrl that sits on the <html> element that handles a few site-wide things.

I wanted populate the <title> tag with translated text. However using the directive creates an html element and the filter is visible as raw ``{{ }}` text. So, reluctantly, I decided to create a scope variable in my SiteCtrl that stores the pagetitle.

$scope.pagetitle = $i18next('ui.pagetitle');

However, this only outputs ui.pagetitle. From my experience with i18next, this means it's translating, but not finding the key. When I put this same line into another controller further down in the DOM, it works fine.

I'm guessing there's something special about the html element. Is there any way i can get this translation to work?

add more tests

We have to add more tests for:

  • sprintf
  • post processors
  • $scope
  • defaultLoadingValue (b757fb8)

advance README

Advance the README.md, so the user knows how to use this directive.
Also add a link to the original i18next project.

Question: Unit-testing in angular issue, $i18next filter not resolving.

So I'm writing unit tests for a service which uses $i18next filter to set up some strings in an object, however when unit testing the service, the strings aren't resolved. I noticed in the README it says For testing purposes set up a server. Don't open your files directly because i18next then fails to load the language files!, but I'm not 100% sure if that is the reason my filters aren't resolving in the service during unit tests. Can someone please expand on that or shed some light on unit testing components that use $i18next? I'm pretty new to unit-testing and haven't gotten any answers so far from google, stack, or the irc channels.

Sorry and thanks!

Note. My gruntfile is set-up to include the i18next and ng-i18next as dependencies.

tag 0.2.7 for bower

Hi @archer96, first thanks for the awesome directive. If its not too much of a bother do you mind adding a tag so bower can pull down version 0.2.7? I would like to get that ng-model bugfix... Thanks!

Compatibilty issue with latest version (1.8.0) of i18next

We just updated to @i18next version 1.8.0 and now we get errors:

TypeError: Cannot read property 'init' of undefined
        at init (/Users/julien/repos/subtome.com/app/bower_components/ng-i18next/dist/ng-i18next.js:20:15)
        at self.$get (/Users/julien/repos/subtome.com/app/bower_components/ng-i18next/dist/ng-i18next.js:81:3)
        at Object.invoke (/Users/julien/repos/subtome.com/app/bower_components/angular/angular.js:3697:17)

Any idea what's going on?

using postProcessor

I would like to add a post processor to i18next configuration. Is it possible to add a way to add one of those through the provider?

create i18next filter

Create a filter to translate strings:

<p>{{ 'hello' | i18next }}</p>
<p>{{ welcome | i18next }}</p>

Also make it possible to pass arguments:

hello: "Hello {{name}}"

scope.this gives problems on IE8

Hi,

on line 212 and 227, the 'scope.this' syntax causes the whole module not being loaded.
I changed

localize(scope.this, element, translationValue);
into
localize(scope, element, translationValue);

and my problem seems gone, I hope. I'm not sure if I broke something.

"IE FIX" comment known issue

Angular adds a comment inside <a> directives to fix a bug on IE8 with mailto: like this:

<a href="" ng-i18next>ns:mykey<!--IE FIX--></a>

You can find this behavior in Angular's source code:

element.append(document.createComment('IE fix'));

This comment is interpreted by ng-i18next as part of the key, and thus breaks any translations in <a> anchors.

Since the support for IE8 is dropped by Angular and ng-i18next, this issue will not be addressed.

If you need to make ng-i18next work on IE8, a good workaround would be to use the directive's attribute syntax instead:

<a href="" ng-i18next="ns:key" />

Ability to opt in for bindOnce

As far as I am able to tell, there is not a way to setup the 'ngi18next' directive to bindOnce. Could the option be added? I noticed something similar was proposed in issue #52 where a 'watchOptions' property was added to the $i18nextProvider. In our application, it would not work to have the watch removed for all translations as there will likely be a mix in most applications. For example when a pluralized translation needs to be displayed due to multiple values being selected.

So, we are looking for something similar to available bind-once directive which allows for things like 'bo-if', etc. In cases where we do not want a watcher, we could use 'bo-ngi18next'.

I'd be happy to help by contributing a solution. Just checking first check and make sure I'm not overlooking a way to accomplish what I need with current implementation.

$digest already in progress

With http://subtome.com we're seeing an odd error:

Error: $digest already in progress
    at Error (<anonymous>)
    at g (https://www.subtome.com/js/angular.min.js:84:377)
    at Object.e.$apply (https://www.subtome.com/js/angular.min.js:88:437)
    at setTranslation (https://www.subtome.com/js/ng-i18next.js:1:326)
    at https://www.subtome.com/js/ng-i18next.js:2:41
    at https://www.subtome.com/js/i18next.js:49:70
    at https://www.subtome.com/js/i18next.js:108:154
    at String.<anonymous> (https://www.subtome.com/js/i18next.js:109:20)
    at Object._each [as each] (https://www.subtome.com/js/i18next.js:17:430)
    at Object.sync._loadLocal (https://www.subtome.com/js/i18next.js:108:369) 

Any idea what that means? Something like https://github.com/BinaryMuse/ngInfiniteScroll/blob/master/build/ng-infinite-scroll.js#L36-L40 may fix it?

Performance degradation since release 0.3.5

Hi,

Could you gave me informations about this patch
1a73ec1#diff-ebf3979692cdbbeda460cd60ac620a9d

Since modification below performance on our site is really degraded.

image

Init time with version 0.3.5
image

Init tile with version 0.3.4
image

As you can see scripting part is 6 seconds longer.

After some investigations, I found that passing the full merge option to translate method trigger in i18next a lot of processing.
Internal method applyReplacement is now executed 58181 times versus 273 times on previous version.

It's not really a bug of ng-i18next but I need to understand what your patch has fixed.

Regards

Latest commit breaks "directives" test :/

Hello,
I'm not sure the latest commit 6f48a0b is 'final' but it breaks the "directives" test, which works fine in b453e03.

Maybe we should write better tests? Do you want me to do so? I'm not familiar with how to do it since it will depend on the language used by the tester, but maybe you have a better idea?

Please, let me know!

Thanks

translate by using content

Make it possible to translate the content of an element.

<p ng-i18next>Hello</p>
<p ng-i18next>{{hello}}</p>

Make sure the replacement is "bind-able"

If the localized string includes angular directives, we need to 'compile' them with the right scope. That works for with {{exp}} and also ng-xxx should the the localized string be some HTML.

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.