Coder Social home page Coder Social logo

martinandert / counterpart Goto Github PK

View Code? Open in Web Editor NEW
242.0 10.0 24.0 184 KB

A translation and localization library for Node.js and the browser.

License: MIT License

JavaScript 99.61% Makefile 0.39%
javascript internationalization localization translation library nodejs

counterpart's Introduction

Counterpart

A translation and localization library for Node.js and the browser. The project is inspired by Ruby's famous I18n gem.

Features:

  • translation and localization
  • interpolation of values to translations (sprintf-style with named arguments)
  • pluralization (CLDR compatible)

Installation

Install via npm:

% npm install counterpart

Usage

Require the counterpart module to get a reference to the translate function:

var translate = require('counterpart');

This function expects a key and options as arguments and translates, pluralizes and interpolates a given key using a given locale, scope, and fallback, as well as interpolation values.

Lookup

Translation data is organized as a nested object using the top-level key as namespace. E.g., the damals package ships with the translation:

{
  damals: {
    about_x_hours_ago: {
      one:   'about one hour ago',
      other: 'about %(count)s hours ago'
    }
    /* ... */
  }
}

Translations can be looked up at any level of this object using the key argument and the scope option. E.g., in the following example, a whole translation object is returned:

translate('damals')  // => { about_x_hours_ago: { one: '...', other: '...' } }

The key argument can be either a single key, a dot-separated key or an array of keys or dot-separated keys. So these examples will all look up the same translation:

translate('damals.about_x_hours_ago.one')          // => 'about one hour ago'
translate(['damals', 'about_x_hours_ago', 'one'])  // => 'about one hour ago'
translate(['damals', 'about_x_hours_ago.one'])     // => 'about one hour ago'

The scope option can be either a single key, a dot-separated key or an array of keys or dot-separated keys. Keys and scopes can be combined freely. Again, these examples will all look up the same translation:

translate('damals.about_x_hours_ago.one')
translate('about_x_hours_ago.one', { scope: 'damals' })
translate('one', { scope: 'damals.about_x_hours_ago' })
translate('one', { scope: ['damals', 'about_x_hours_ago'] })

The separator option allows you to change what the key gets split via for nested objects. It also allows you to stop counterpart splitting keys if you have a flat object structure:

translate('damals.about_x_hours_ago.one', { separator: '*' })
// => 'missing translation: en*damals.about_x_hours_ago.one'

Since we changed what our key should be split by counterpart will be looking for the following object structure:

{
  'damals.about_x_hours_ago.one': 'about one hour ago'
}

The setSeparator function allows you to globally change the default separator used to split translation keys:

translate.setSeparator('*') // => '.' (returns the previous separator)

There is also a getSeparator function which returns the currently set default separator.

Interpolation

Translations can contain interpolation variables which will be replaced by values passed to the function as part of the options object, with the keys matching the interpolation variable names.

E.g., with a translation { foo: 'foo %(bar)s' } the option value for the key bar will be interpolated into the translation:

translate('foo', { bar: 'baz' }) // => 'foo baz'

Pluralization

Translation data can contain pluralized translations. Pluralized translations are provided as a sub-object to the translation key containing the keys one, other and optionally zero:

{
  x_items: {
    zero:  'No items.',
    one:   'One item.',
    other: '%(count)s items.'
  }
}

Then use the count option to select a specific pluralization:

translate('x_items', { count: 0  })  // => 'No items.'
translate('x_items', { count: 1  })  // => 'One item.'
translate('x_items', { count: 42 })  // => '42 items.'

The name of the option to select a pluralization is always count, don't use itemsCount or anything like that.

Note that this library currently only supports an algorithm for English-like pluralization rules (see locales/en.js. You can easily add pluralization algorithms for other locales by adding custom translation data to the "counterpart" namespace. Pull requests are welcome.

As seen above, the count option can be used both for pluralization and interpolation.

Fallbacks

If for a key no translation could be found, translate returns an error string of the form "translation missing: %(key)s".

To mitigate this, provide the fallback option with an alternate text. The following example returns the translation for "baz" or "default" if no translation was found:

translate('baz', { fallback: 'default' })

Dealing with missing translations

When a translation key cannot be resolved to a translation, regardless of whether a fallback is provided or not, translate will emit an event you can listen to:

translate.onTranslationNotFound(function(locale, key, fallback, scope) {
  // do important stuff here...
});

Use translate.offTranslationNotFound(myHandler) to stop listening to missing key events.

As stated in the Fallbacks section, if for a key no translation could be found, translate returns an error string of the form "translation missing: %(key)s".

You can customize this output by providing your own missing entry generator function:

translate.setMissingEntryGenerator(function(key) {
  // console.error('Missing translation: ' + key);
  return 'OMG! No translation available for ' + key;
});

Locales

The default locale is English ("en"). To change this, call the setLocale function:

translate.getLocale()     // => 'en'
translate.setLocale('de') // => 'en' (returns the previous locale)
translate.getLocale()     // => 'de'

Note that it is advised to call setLocale only once at the start of the application or when the user changes her language preference. A library author integrating the counterpart package in a library should not call setLocale at all and leave that to the developer incorporating the library.

In case of a locale change, the setLocale function emits an event you can listen to:

translate.onLocaleChange(function(newLocale, oldLocale) {
  // do important stuff here...
}, [callbackContext]);

Use translate.offLocaleChange(myHandler) to stop listening to locale changes.

You can temporarily change the current locale with the withLocale function:

translate.withLocale(otherLocale, myCallback, [myCallbackContext]);

withLocale does not emit the locale change event. The function returns the return value of the supplied callback argument.

Another way to temporarily change the current locale is by using the locale option on translate itself:

translate('foo', { locale: 'de' });

There are also withScope and withSeparator functions that behave exactly the same as withLocale.

Fallback Locales

You can provide entire fallback locales as alternatives to hard-coded fallbacks.

translate('baz', { fallbackLocale: 'en' });

Fallback locales can also contain multiple potential fallbacks. These will be tried sequentially until a key returns a successful value, or the fallback locales have been exhausted.

translate('baz', { fallbackLocale: [ 'foo', 'bar', 'default' ] })

Globally, fallback locales can be set via the setFallbackLocale method.

translate.setFallbackLocale('en')
translate.setFallbackLocale([ 'bar', 'en' ]) // Can also take multiple fallback locales

Adding Translation Data

You can use the registerTranslations function to deep-merge data for a specific locale into the global translation object:

translate.registerTranslations('de', require('counterpart/locales/de'));
translate.registerTranslations('de', require('./locales/de.json'));

The data object to merge should contain a namespace (e.g. the name of your app/library) as top-level key. The namespace ensures that there are no merging conflicts between different projects. Example (./locales/de.json):

{
  "my_project": {
    "greeting": "Hallo, %(name)s!",
    "x_items": {
      "one":   "1 Stück",
      "other": "%(count)s Stücke"
    }
  }
}

The translations are instantly made available:

translate('greeting', { scope: 'my_project', name: 'Martin' })  // => 'Hallo, Martin!'

Note that library authors should preload their translations only for the default ("en") locale, since tools like webpack or browserify will recursively bundle up all the required modules of a library into a single file. This will include even unneeded translations and so unnecessarily bloat the bundle.

Instead, you as a library author should advise end-users to on-demand-load translations for other locales provided by your package:

// Execute this code to load the 'de' translations:
require('counterpart').registerTranslations('de', require('my_package/locales/de'));

Registering Default Interpolations

Since v0.11, Counterpart allows you to register default interpolations using the registerInterpolations function. Here is an example:

translate.registerTranslations('en', {
  my_namespace: {
    greeting: 'Welcome to %(app_name)s, %(visitor)s!'
  }
});

translate.registerInterpolations({ app_name: 'My Cool App' });

translate('my_namespace.greeting', { visitor: 'Martin' })
// => 'Welcome to My Cool App, Martin!'

translate('my_namespace.greeting', { visitor: 'Martin', app_name: 'The Foo App' })
// => 'Welcome to The Foo App, Martin!'

As you can see in the last line of the example, interpolations you give as options to the translate function take precedence over registered interpolations.

Using a key transformer

Sometimes it is necessary to adjust the given translation key before the actual translation is made, e.g. when keys are passed in mixed case and you expect them to be all lower case. Use setKeyTransformer to provide your own transformation function:

translate.setKeyTransformer(function(key, options) {
  return key.toLowerCase();
});

Counterpart's built-in key transformer just returns the given key argument.

Localization

The counterpart package comes with support for localizing JavaScript Date objects. The localize function expects a date and options as arguments. The following example demonstrates the possible options.

var date = new Date('Fri Feb 21 2014 13:46:24 GMT+0100 (CET)');

translate.localize(date)                       // => 'Fri, 21 Feb 2014 13:46'
translate.localize(date, { format: 'short' })  // => '21 Feb 13:46'
translate.localize(date, { format: 'long' })   // => 'Friday, February 21st, 2014 13:46:24 +01:00'

translate.localize(date, { type: 'date' })                  // => 'Fri, 21 Feb 2014'
translate.localize(date, { type: 'date', format: 'short' }) // => 'Feb 21'
translate.localize(date, { type: 'date', format: 'long' })  // => 'Friday, February 21st, 2014'

translate.localize(date, { type: 'time' })                  // => '13:46'
translate.localize(date, { type: 'time', format: 'short' }) // => '13:46'
translate.localize(date, { type: 'time', format: 'long' })  // => '13:46:24 +01:00'

translate.registerTranslations('de', require('counterpart/locales/de'));
translate.localize(date, { locale: 'de' })  // => 'Fr, 21. Feb 2014, 13:46 Uhr'

Sure, you can integrate custom localizations by adding to or overwriting the "counterpart" namespace. See locales/en.js and locales/de.js for example localization files.

As an instance

You can invoke an instance of Counterpart should you need various locales displayed at once in your application:

var Counterpart = require('counterpart').Instance;

var instance = new Counterpart();

instance.registerTranslations('en', { foo: 'bar' });
instance.translate('foo');

Error handling

When a translation fails, translate will emit an event you can listen to:

translate.onError(function(err, entry, values) {
  // do some error handling here...
});

Use translate.offError(myHandler) to stop listening for errors.

Contributing

Here's a quick guide:

  1. Fork the repo and make install.
  2. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate: make test.
  3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or are fixing a bug, we need a test!
  4. Make the test pass.
  5. Push to your fork and submit a pull request.

License

Released under The MIT License.

counterpart's People

Contributors

agirton-twitter avatar andrealbinop avatar bitfrost avatar codefo avatar jiripudil avatar justinwoo avatar martinandert avatar rvdkooy avatar ryanseddon avatar takakoshimizu avatar temaruk avatar yanndinendal 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

counterpart's Issues

Emit Event when translation is not found

Is there a way to trigger an event when translation is not found? Basically when the fallback is used.

This is important because missing translations should not be silently ignored but handled appropriately for each case.

ex. Translation not found > send request to server and log an error

onError callback not getting called when interpolation error occurs

var translate = require('counterpart')

translate.onError(function(err, entry, values) {
  // not getting called
});

translate.registerTranslations('en', { hello: 'Hello, %(name)s!' });

// This is a bad call and will throw an error but won't call the onError callback
translate('hello');

The error gets caught as expected, but it throws the standard one instead of calling my custom error handler.

Everything else works fine, so it makes me think it's isolated to this feature.

Great library BTW, the ease of use and simplicity is fantastic. The consistent structure of use in particular makes extracting the key catalog from code much easier!

Cannot use Link of 'react-router' as component

I tried to pass a non native HTML element as component like this:

import { Link } from 'react-router'

<Translate to='/courses' component='Link' content='goto-course-list' />

but I got this error, seems like the component was

Warning: link is a void element tag and must not have `children` or use `props.dangerouslySetInnerHTML`. Check the render method of Interpolate.

warning @ warning.js?0260:45assertValidProps @ ReactDOMComponent.js?1302:200ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:454ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactMultiChild.Mixin.mountChildren @ ReactMultiChild.js?c87d:241ReactDOMComponent.Mixin._createContentMarkup @ ReactDOMComponent.js?1302:591ReactDOMComponent.Mixin.mountComponent @ ReactDOMComponent.js?1302:479ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37ReactCompositeComponentMixin.mountComponent @ ReactCompositeComponent.js?cd59:225wrapper @ ReactPerf.js?ef93:66ReactReconciler.mountComponent @ ReactReconciler.js?6bfa:37mountComponentIntoNode @ ReactMount.js?2f23:266Mixin.perform @ Transaction.js?6dff:136batchedMountComponentIntoNode @ ReactMount.js?2f23:282Mixin.perform @ Transaction.js?6dff:136ReactDefaultBatchingStrategy.batchedUpdates @ ReactDefaultBatchingStrategy.js?ef70:62batchedUpdates @ ReactUpdates.js?ce09:94ReactMount._renderNewRootComponent @ ReactMount.js?2f23:476wrapper @ ReactPerf.js?ef93:66ReactMount._renderSubtreeIntoContainer @ ReactMount.js?2f23:550ReactMount.render @ ReactMount.js?2f23:570wrapper @ ReactPerf.js?ef93:66(anonymous function) @ index.js?dadc:17(anonymous function) @ bundle.js:3121__webpack_require__ @ bundle.js:521fn @ bundle.js:76(anonymous function) @ bundle.js:552__webpack_require__ @ bundle.js:521(anonymous function) @ bundle.js:544(anonymous function) @ bundle.js:547
client.js?3ac5:53 [HMR] connected

Uncaught ReferenceError: isPlainObject is not defined

Hi,

I'm having an issue using counterpart with webpack. When doing:

import counterpart from 'counterpart';

It fails with Google chrome with the following error:

Uncaught ReferenceError: isPlainObject is not defined

When I open the web developer tools console and reload, it works. It only works with the developer tools open, but fails again when I close it. It doesn't fail in Firefox or Safari.

Do you have any ideas about what may be causing this issue?

Thanks in advance

Issue when using interpolation with numbers

I have the following setup for a table footer with pagination info:

Translations:

app: {
  footer: 'Zeige Einträge %(start)s bis %(end)s von %(total)s'
}

I use the component like this:

<Translate content="app.footer"
  start={this.state.skip + 1}
  end={this.state.skip + this.state.top}
  total={this.state.total}
/>

The translation works perfectly on first load, but when I change the values for either top or skip the calculation fails, instead the numbers get concatenated like strings. See screenshot:
screenshot

Am I missing something? Is there a possibility to interpolate as a number, like %(start)n instead of
%(start)s?

Error: [sprintf] %

Hey, nice library.

How do I escape a % in the actual string, ie

c=require('counterpart')
c.registerTranslations('en', {'hello':'100%'})
c('hello')

Error: [sprintf] %
    at Function.str_format.parse (~/code/counterpart/node_modules/sprintf/lib/sprintf.js:233:11)
    at str_format (~/code/counterpart/node_modules/sprintf/lib/sprintf.js:77:48)
    at interpolate (~/code/counterpart/index.js:219:10)
    at translate (~/code/counterpart/index.js:140:13)
    at repl:1:2
    at REPLServer.self.eval (repl.js:112:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:117:20)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)

Fallback does not work with string '0'

I've had to put this check in place to handle strings that are 0 and enable fallback to work successfully.

return label === '0' ? counterpart(table.columns.${label}, { fallback: label }) : label;

Do you plan to update the used counterpart version in your other projects?

We're currently using some of your projects and would like to go to the latest counterpart version and ditch our own forks. But this would need some updates on https://github.com/martinandert/react-translate-component, https://github.com/martinandert/react-ago-component, https://github.com/martinandert/react-interpolate-component and https://github.com/martinandert/damals maybe some more :-/

Most of them have counterpart ~0.11.* as "peer dependencie.

Greetings from Berlin,
cainvommars

Missing translation:

My problem: Missing translation: en.null.invoices.payment_termen

code:

const t = require("counterpart");
...
{
  lang : t('payment_termen', {locale: lang});;
}

output:
{
"en": Missing translation: en.null.invoices.payment_termen
}

i have found that scope is set to "null" and i can't understand why

Thanks.

Bad iteration if language fallback fails

counterpart/index.js

Lines 223 to 224 in e1e4204

for (var ix in fallbackLocales) {
var fallbackLocale = fallbackLocales[ix];

I'm encountering this using bitshares-ui which uses this library to handle translations.

This library uses for...in to iterate over fallback language array, but if the fallback fail the code will continue to iterate over other objects in the array, like in the picture below. Using other for methods would avoid the problem.

0029-12-28 3 57 49


You may want to avoid for...of though as it would possibly break some ES6-incompatible configurations... C-style for works.

missing translation: nl.counterpart.pluralize

Have pluralizarions working in English but when switching to dutch I get this error

missing translation: nl.counterpart.pluralize

Registered locale data is here

EN:

  "terms": {
    "item": {
      "one": "Item",
      "other": "Items",
      "zero": "Items",
      "new": "New Item"
    },

NL:

  "terms": {
    "item": {
      "one": "Document",
      "other": "Documenten",
      "zero": "Documenten",
      "new": "Nieuw document"
    },

The EN works fine but NL throws the error

Interpolations not working

Seems to be unable to interpret %(key) here:

https://github.com/maritz/node-sprintf/blob/master/lib/sprintf.js#L199

I noticed that npm's sprintf module is deprecated in favor of sprintf-js. Haven't tried swapping it in, but it's probably worth a look.

To reproduce in Node,

counterpart = require('counterpart');
counterpart.registerTranslations('en', {foo: 'Foo is %(what).'});
counterpart('foo', {what: 'cool'});

results in

Error: [sprintf] %(what).
    at Function.str_format.parse (/node_modules/counterpart/node_modules/sprintf/lib/sprintf.js:231:11)
    at str_format (/node_modules/counterpart/node_modules/sprintf/lib/sprintf.js:75:48)
    at Counterpart._interpolate (/node_modules/counterpart/index.js:233:10)
    at Counterpart.translate (/node_modules/counterpart/index.js:129:18)
    at translate (/node_modules/counterpart/index.js:286:29)
    at repl:1:2
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)

Name of the option to select a specific pluralization

Hi!
I have been using your wonderful library (by react-translate-component).
When I used pluralization, I was faced with a problem. I used notationsCount instead of count as name for option to select a specific pluralization and got an error Uncaught Invariant Violation: Interpolate expects either a format string as only child or a 'format' prop with a string value.
It took some time until I figured it out.
Please emphasize in the documentation the fact that the name of the option to select a specific pluralization must be count.

split confusion

I'm unclear about what the docs are saying about 'splitting'. Can someone explain better? This doesn't seem grammatical to me

The separator option allows you to change what the key gets split via for nested objects. It also allows you to stop counterpart splitting keys if you have a flat object structure:

`translate` as an instance

I'm working on a plugin where it will be possible to have multiple instances on a page using different locales. I couldn't find a way to do it, but I'm proposing something like this:

var translate = new Counterpart();

translate.setLocale('en');
translate.registerTranslations('en', {foo: 'bar'});

translate('foo'); // bar

You can then set the locale per instance, instead of globally.

Fallback mechanism automatically searching a default resource file?

The fallback mechanism requires the default parameter to be supplied on each call. It would be nice if we a method could be added which would look up a default translation file if the translation did not exist. In many cases we are happy if the english translation (or another default language) is provided if the translation does not exist in the language. it is cumbersome to have to supply the default param each time.

variables doesn't work

I read all documentation and wrote this code:

{
  followAuthor: 'Author %(author) added your subscription list',
}
Language.translate('followAuthor', { author: 'test' });

and get:

SyntaxError: [sprintf] unexpected placeholder

registerInterpolations doesn't seem to work

var translate = require('counterpart');
translate.registerTranslations('en', {'hello':'Hello from %(brand)s!'})
translate.registerInterpolations({brand:'Z'})
translate('hello')
>'Hello from %(brand)s!'

Passing in {brand:'Z'} does work.

translation file key has dots but is not a nested object

I have a translation service that returns a flat object that is 1 level deep and all keys are namespaced using a dot as seperator for various reasons. Is there an option to tell counterpart to not split via dots?

{
  'namespace.subject' : 'A subject'
}

Would you be open to a PR adding this if it's not already possible?

Feature request: Multiple counts

It would be nice to be able to specify multiple counts in case a string needs to report two or more things that may or may not be singular.

Eg.

  • there is one apple and one pear
  • there are %(count1)s apples and one pear
  • there is one apple and %(count2)s pears
  • there are %(count1)s apples and %(count2)s pears

Locales are inheritance

Why the locale change for all not for current browser # user.

When i get 2 instace of my site and switch language, language is switched in both. Why its isn;t switched for browser window?

Passing react dom element to a placeholder

We are using counterpart heavily and it would be great if we can pass react dom element to a placeholder
like so

// imagine the following entry
counterpart.registerTranslations('en', {
 departures: {
      available_of: '%(available)s available of total %(max)s pax'
    }
})

// and display it using
  const available = (count) => {
    return (<b>{count}</b>);
  };
 translate('departures.available_of', {available: available(departure.available), max: departure.max})

Is it possible to implement this, please?

Pluralization Issue

With:

module.exports = {
  "greeting": "Hello, %(name)s!",
  "x_nights": {
    "zero": "No Night",
    "one":   "1 Night",
    "other": "%(count) Nights"
  }
}

executing:

translate('x_nights.other', {count: 3}) results in:

Uncaught Error: [sprintf] %(count) Nächte(…)

problem with html content that contains a "%"

Hi,
I'm getting an error when a translation contains a percentage symbol (%).

Uncaught Error: [sprintf] %

Any idea on how I can get around this?

Edit: I tried using the entity "%" but the issue still persists

Why is translationnotfound fired only when fallback is provided?

I was wondering, is there some special reasoning behind that decision? Even if I don't provide a fallback, I'd still like to be able to e.g. throw an error when developing or log the information to the server when on production, so that I can find out about the missing translation easily

Consider switching to a regularly maintained sprintf package

Thank you for your time and effort in creating this awesome package!

It occurred to me that switching to https://github.com/alexei/sprintf.js might be as simple as 2 line changes. This is the lib on which the currently used (https://github.com/maritz/node-sprintf) is based (as mentioned in its docs).

One benefit I can see over the old one (there might be many more) is that interpolations would support computed values (functions). Would have been really useful for me. :)

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.