GithubHelp home page GithubHelp logo

eligrey / l10n.js Goto Github PK

View Code? Open in Web Editor NEW
391.0 23.0 68.0 112 KB

Passive localization JavaScript library

Home Page: http://purl.eligrey.com/l10n.js

License: Other

HTML 45.75% JavaScript 50.60% CSS 3.65%

l10n.js's Introduction

l10n.js

l10n.js is a JavaScript library that enables passive localization through native JavaScript methods, gracefully degrading if the library is not present. You can make Ajax applications, JavaScript libraries, etc. that can be localized but not require l10n.js to function. There is already a placeholder method for all API calls as specified in the ECMAScript specification and is present in all JavaScript engines, so when l10n.js isn't present, your application works fine.

Demo

This repository includes a simple demo that you can try out on your webserver.

If you know a language that isn't currently supported in the demo, I encourage you to contribute a localization by sending me your own localizations, either through GitHub or directly. The following strings would need to be localized:

  • %title to {Locale} - l10n.js demo in the locale.
  • %info to You are viewing a {locale} localization of this page. in the locale.
  • Optionally, %locale.dir to rtl if the locale uses right-to-left directionality.

Supported Browsers

  • Internet Explorer 5+
  • Firefox 2+
  • Opera 9+
  • Google Chrome 1+
  • Safari 4+

Getting Started

  1. Download l10n.js.
  2. Localize strings used in your JavaScript application. See the demo localizations file for an example localizations file. You can also specify external localizations in your main localizations file by assigning a URL string to a language code, such as "en-us": "localizations/en-us.json".
  3. Include the appropriate link elements, as described in the usage section, anywhere in your document. I recommend putting it in the document's <head>.
  4. Place <script type="text/javascript" src="path/to/l10n.js"></script> anywhere after the <link> tag.
  5. Call toLocaleString() on any strings you wish to localize.

Usage

Localizing strings

Calling toLocaleString() on every localizable string can create a lot of extra typing and bloat for sending your JavaScript down the wire. I recommend using the following helper function to localize strings. The reason I don't define this in l10n.js is to not introduce any new globals, which keeps l10n.js a one of the JavaScript libraries least-prone to conflicts with other libraries.

var l = function (string) {
    return string.toLocaleString();
};

With this helper function, you can start writing l("Your localizable string") instead of "Your localizable string".toLocaleString(). I chose l instead of _ (an underscore), because it's easier to spot so you can quickly skim your code to see which strings are localizable.

Variable replacement

If you don't mind requiring l10n.js for your JavaScript application or library to function, I suggest using short variable strings instead of default strings. It saves bandwidth by decreasing the size of localization files, and it enables you to write nice, short code as such in the following.

  • document.title = l("%title.search")
    • Example results: "Search - Acme, Inc."
  • confirm(l("%confirm.deleteAccount"))
    • Example results: "Are you sure you want to delete your account?"
  • link.href = "http://www.google." + l("%locale.tld")
    • Example results: "http://www.google.co.uk"

Often, string concatenation is used instead of replacement in JavaScript. With l10n.js, to make localization easier, you may have to use replacements instead. You might want to use a JavaScript library that implements something similar to C++'s sprintf(). A nice JavaScript implementation I'd recommend is php.js's sprintf().

When localizations are downloaded

If you are using single localization URLs (<link rel="localization" hreflang="..." href="..." type="application/vnd.oftn.l10n+json"/>), they will only be downloaded when needed. If you are using multiple localizations in one (<link rel="localizations" href="..." type="application/vnd.oftn.l10n+json"/>), then the file will be downloaded right away, but externally linked localizations in the localization file will not be. If you provide an interface for your users to change locales, any non-loaded localization files will be loaded when necessary.

Including localizations with link elements

Multiple localizations can be included with one localization JSON file, with all of the top properties being language codes. Instead of putting all of the localized strings directly in the file, you may want to assign a specifc localization JSON URL to each locale, as to save bandwidth by only downloading locales the user needs.

The following is an example localization file for <link rel="localizations" href="path/to/localizations.json" type="application/vnd.oftn.l10n+json"/>.

{
  "en-US": {
      "What is your favourite colour?": "What is your favorite color?"
  },
  "fr": "path/to/french-localization.json"
}

Using localization files is the same as calling String.toLocaleString() witht the JSON localizations object as the first parameter.

You can also include single localizations by specifying the standard HTML5 hreflang link element attribute and using a rel of localization instead of localizations with an 's', as shown in the following.

<link rel="localization" hreflang="en-US" href="american-english.json" type="application/vnd.oftn.l10n+json"/>

The JSON file for the localization might look like the following.

{
    "What is your favourite colour?": "What is your favorite color?"
}

API

Strong and emphasized text has titles (which can be viewed by hovering your cursor over them) containing their type if they are not functions or return type if they are.

Methods

String.toLocaleString([localizations])
If localizations is an object, it is added to the localizations.
If localizations is a string, it is requested as JSON and then added to the localizations.
If localizations is false, then all localizations are reset.
If localizations is an object, and a locale is false, then all localizations for that locale are reset.

The string representation of the String contructor is returned, to maintain backwards compatibility with any code using this method to actually get it.

<h4>Examples</h4>
<ul>
  <li>
    Loading a localizations JSON file:
    <pre><code>String.toLocaleString(<strong title="String">"path/to/localizations.json"</strong>)</code></pre>
  </li>
  <li>
    Defining localizations directly:
    <p>
      The nearest locale to the user's locale that has the string being localized is
      used in localization.
    </p>
    <pre><code>String.toLocaleString({
"es": { // Spanish
    "Hello, world!": "¡Hola, mundo!"
    // more localizations...
},
"en-US": { // American English
    "Hello, world!": "Hello, America!" // Locale-specific message
    // more localizations...
},
"en-GB": false, // resetting British English localizations
// Specifying external localization JSON for Japanese:
// The URL isn't requested unless the user's locale is Japanese
"ja": "localizations/ja.json"

})

  • Resetting all localizations:
    String.toLocaleString(false)
  • aString.toLocaleString()
    Returns the localized version of aString in the user's locale, if available. Otherwise, it returns the same string.

    Fields

    String.locale
    A configurable string which represents the language code of the locale to use for localization. It defaults to the user's own locale.
    String.defaultLocale
    A configurable string which represents the language code of the default locale to use for localization if no localizations are available in the user's locale. By default this is not configured, and may be ignored if you are using l10n.js for passive-only localizations.

    Default locale

    The "" (empty string) locale is the default locale, where you can specify default or fallback strings.

    l10n.js's People

    Contributors

    alxandr avatar destan avatar devyn avatar eligrey avatar hashanp avatar madskonradsen avatar maklesoft avatar mumez avatar neilfraser avatar petrkle avatar rojakcoder avatar sebastianberns avatar valkuc avatar yeco 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  avatar  avatar  avatar  avatar  avatar  avatar

    l10n.js's Issues

    Problem and a possible fix for Chrome 39

    Hi,

    Using the 2-year old Chrome 39 (2014-11), I've got a "use const in strict mode" syntax error in l10n.js:

            return Function.prototype[$to_locale_string].apply(String_ctr, arguments);
        }
        , loadFromDisk = String_ctr[$to_locale_string] = function (uri) {
                const fs = require('fs');
                ^^^^^
    

    By removing the strict mode or changing const to var, it was possible to fix the problem, for example:

    diff -u node_modules/l10n-for-node.old/l10n.js node_modules/l10n-for-node/l10n.js
    --- node_modules/l10n-for-node.old/l10n.js	2016-12-01 13:41:50.301318129 +0100
    +++ node_modules/l10n-for-node/l10n.js	2016-12-01 13:43:31.765314513 +0100
    @@ -130,7 +130,7 @@
     	return Function.prototype[$to_locale_string].apply(String_ctr, arguments);
     }
     , loadFromDisk = String_ctr[$to_locale_string] = function (uri) {
    -        const fs = require('fs');
    +        var fs = require('fs');
             var read = fs.readFileSync(uri, 'utf8');
             return JSON.parse(read);
    

    Thanks for your work,
    Laszlo

    Do you need to include a translation when one isn't needed?

    Just starting to use this library and wondering for like the default language or similar ones do you need to provide the translation if one is not needed?

    For example, say your translation is l("my message") then you would normally have to do something like this:

    {
      "en-US": {
          "my message": "my message",
          "color": "color"
      },
      "en-GB": {
          "my message": "my message",
          "color": "colour"
      },
    }

    Whereas, if not already an acceptable way to do it, something like this would save a lot of repeated data and code bloat:

    {
      "en-US": {
    
      },
      "en-GB": {
          "color": "colour"
      },
    }

    So basically if it didn't find the translation then the text would remain the same; in this instance we would be using en-US as our default (writing) language and hence no translations are needed and en-GB is very similar so the file should only need to contain the translations that actually need to be translated.

    Is this an acceptable way of doing it or does all translations have to be put in the files whether they need translating or not?

    Cannot call method 'valueOf' error

    I am getting an error when calling some jQuery ajax functions that have strings in the data object eg:

    $.ajax({
    data: { ..strings... }
    ...
    

    Here is the top of the trace:

    Uncaught TypeError: Cannot call method 'valueOf' of undefined l10n.js:148
    String_ctr.(anonymous function) l10n.js:148
    add jquery-1.10.2.js:7499
    buildParams jquery-1.10.2.js:7551
    buildParams jquery-1.10.2.js:7546
    jQuery.param jquery-1.10.2.js:7519
    jQuery.extend.ajax ...

    When I print my data object that I am sending into the above ajax function it looks something like:

    f: "..."
    limit: 4
    page: 0
    o: Object
    { 
        0: "1"
        toLocaleString: function () {
        __proto__: Object
    
    }
    

    On these strings I do not want to do translation, so I make a small change into l10n.js at line 143:

    if(this === undefined) return false;
    

    This stops the error, and translation seems to be fine for everything else, but is there a better way?

    Use different locale than the selected one

    Hi all!

    First of all, tthis is not an issue, but rather a question.
    But since I couldn't find an answer, here goes:
    Is it possible to programatically translate a resource?

    In the current app I am developing, we give the user the option to change the current locale.
    However it seems easy at first, we need to warn the user about the language being changed (not in its current locale, but rather in the option's locale).

    Something like <locale>: <locale_warning>

    English: Warning, the application will be set to english.
    Português: Aviso, o idioma da aplicação mudará para português.
    

    Best regards,
    tbragaf

    Loading language files fails on some browsers due to inconsistent status codes

    In some browsers/environments the request seems to finish with a status code of 0 even though the request was successful. I've experienced this in the iOS web view (using Cordova) but I'm sore there are other environments where this happens. I suggest basing success/failure on a successful parsing of the response text instead of relying on possibly inconsistent status codes.

    Synchronous XMLHttpRequest

    Hi! i'm getting this error:

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.

    from

    req.open("GET", uri, FALSE);
    

    i know the line above that one says:

    // sadly, this has to be blocking to allow for a graceful degrading API

    but is there a solution to fix this warning?

    Cannot get this to work...

    Ok since my other questions I have been testing this out and I cannot seem to get it to work in any manner using a .json file included as per the instructions under the Usage section, it seems to take no notice of it whatsoever.

    I then tried the way it was done in the Demo section and I got it to work, however it doesn't seem to honor country code locales, eg:

    With that in mind I'm unsure you even set the Language/locale you wish to use if you aren't using the link tag such as:

    <link rel="localization" hreflang="en-US" href="american-english.json" type="application/vnd.oftn.l10n+json"/>

    Does the script look at the value of the lang attribute of the html tag?

    Anyway, I have it set as such:

    <html lang="en-GB">

    ...and then I have included the main library followed by a .js file with this inside it:

    String.toLocaleString({
        "en": {
            "Hello!": "Hello!!!!!!!!"
        },
        "en-GB": {
            "Hello!": "Hola!"
        },
        "en-AU": {
            "Hello!": "Hola!!!!!!!!!!!"
        }
    });

    When I do any translations this will output: Hello!!!!!!!! when it should output Hola!

    If I only include the en-GB locale such as:

    String.toLocaleString({
        "en-GB": {
            "Hello!": "Hola!"
        }
    });

    Then it doesn't do anything and just outputs the same text as I passed in.

    Can you please advise?

    Thanks!

    IOS Translation

    Hey man, I am having trouble getting this to work when running in an IOS app. It seems like the string prototype is not getting the new method. Has this been tested in that env?

    Bower

    Hi,

    In order for Bower to work, you need to add tags for each version (this is equivalent to npm's publish functionality).

    In case you haven't done this:

    1. Add a version property to your bower.json like "0.1.0".
    2. Add a tag to your local repo: git tag -a v0.1.0 -m 'my version 0.1.0'
    3. Push tags to Github: git push origin --tags

    (Note that in Windows command line, double quotes are needed for step 2.)

    Russian l10n for demo

    Please, use:
    "ru": {
    "%title": "Русский - l10n.js demo",
    "%info": "Вы просматриваете Русскую версию этой страницы."
    },

    Support format {"property":{"lang1":"localized message in lang1"}}

    I am working in a project in which we want to process a json such as:
    { "id":0, "name":"monopoly","description":
    {"en":"Monopoly is a board game that originated in the United States in 1903"
    ,"es":"Monopoly es un juego de mesa de intercambio y de bienes raíces"
    }}

    I like the easiness of this library and would like to contribute a patch to allow processing this kind of formats. I imagine it like this:

    String.toLocaleString(retrievedObjectWithLocalizedData,"reverseFormat");
    "description".toLocaleString();

    We want to opt for this format because the localized data is editable and stored in the database.
    As such, it makes a lot of sense to return localization values together with queried data.

    Do you find it worth the extra complexity and effort as to accept a PR?
    Do you have some feedback, syntactic preferences, or any concerns?

    Can you do translations with numbers?

    Just wondering what if you wanted to do translation on a string that has a number in it?

    For example:

    There (is,are) {n} cat(s)

    So what it would do is find the translation string to translate the words, choose the correct term between is and are, show the locale specific number based on what number you passed in (somehow) and also display either the non-plural or plural version of the word cat.

    ...or is this outside this library's scope?

    Thanks!

    ReferenceErrors in browserless environment

    An issue occurs when L10N is being used in a browserless environment, such as being run directly using Node.

    The issues largely come from the assumption that certain objects will exist, such as self, XMLHttpRequest and document, with the former two causing ReferenceErrors when they are reached in the code. This is particularly a problem when it comes to running Unit Tests on localization code inside environments like Mocha.

    The errors in question are as follows:

    ReferenceError: self is not defined at l10n.js:20:9

    and

    ReferenceError: XMLHttpRequest is not defined at l10n.js:196:11

    I have a proposed set of changes to fix this issue for Node that I can create a PR for, if it is considered something that is in scope for the library to handle.

    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.