1.1.1 • Published 10 months ago

bc-gettext-utils v1.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
10 months ago

Bulletcode gettext utilities

bc-gettext-utils is a toolset for Node.js which helps creating and updating translations in a format compatible with gettext .po and .mo files. It extracts translatable strings from JavaScript, .NET and PHP source files and merges extracted translations with existing ones.

In order to load and save translations in .po and .mo formats, use the gettext-parser library.

Usage

Install using npm:

npm install bc-gettext-utils

Extract translations

Use the extractors collection of functions to extract translatable strings from source files, e.g.:

const { translationBuilder, extractors } = require( 'bc-gettext-utils' );

const builder = translationBuilder();

builder.add( file, extractors.js( text, [options] ) );
builder.add( file, extractors.vue( text, [options] ) );
builder.add( file, extractors.cs( text, [options] ) );
builder.add( file, extractors.cshtml( text, [options] ) );
builder.add( file, extractors.xaml( text, [options] ) );
builder.add( file, extractors.php( text, [options] ) );

const translations = builder.translations;
const count = builder.count;

Where:

  • file is the path of the source file to be included in the comments
  • text is the source file contents as a UTF-8 string
  • options is the optional configuration object (see below)

Available extractors:

  • extractors.js - JavaScript files
  • extractors.vue - Vue single-file components
  • extractors.cs - C# files
  • extractors.cshtml - Razor pages and MVC views
  • extractors.xaml - XAML files
  • extractors.php - PHP files

The object returned by builder.translations follows the format used by gettext-parser, e.g.:

{
  "": {
    "example": {
      "msgid": "example",
      "msgstr": [ "" ],
      "comments": {
        "reference": "/path/to/file:123"
      }
    }
  },
  "context": {
    "another example": {
      "msgctxt": "context",
      "msgid": "another example",
      "msgstr": [ "" ],
      "comments": {
        "reference": "/path/to/file:256"
      }
    }
  }
}

The number of extracted unique messages is available as builder.count.

JavaScript and C

The following functions or methods are recognized in JavaScript and C# code:

_( "text" );
_p( "context", "text" );
_n( "text", "plural text" );
_pn( "context", "text", "plural text" );

Additional arguments are ignored. The names of these functions can be customized by passing additional options to the extractor, for example:

builder.add( file, extractors.js( text, file, {
  string: '_',
  particularString: '_p',
  pluralString: '_n',
  particularPluralString: '_pn',
} ) );

Multiple names can be specified by passing an array.

Note that string literals must be used for the extraction to work. In JavaScript, 'single quoted' and "double quoted" strings are supported. In C#, "regular" and @"verbatim" string literals can be used.

Concatenation of multiple string literals using the + operator is also supported:

_( "this is a long text\n"
 + "and this is another line" );

In C#, translatable strings are also extracted from the Display attribute and the ErrorMessage property of validation attributes, for example:

[Required( ErrorMessage = "This field is required." )]
[Display( Name = "First Name" )]
public string FirstName { get; set; }

The names of the attribute and property can be customized by passing additional options to the extractor, for example:

builder.add( file, extractors.cs( text, file, {
  displayAttribute: 'Display',
  errorMessageProperty: 'ErrorMessage',
} ) );

Vue

In Vue single-file components, translatable strings can be placed in the following locations:

  • text interpolation using the "Mustache" syntax: <p>{{ _( 'text' ) }}</p>
  • attribute bindings: <a v-bind:title="_( 'text' )">
  • shorthand attribute bindings: <a :title="_( 'text' )">
  • the <script> block

Razor

In Razor .cshtml files, translatable strings are extracted from:

  • Razor expressions: @_( "text" )
  • Razor code blocks: @{ string title = _( "text" ); }
  • control structures - conditionals, loops, etc.: @if ( a > 0 ) { title = _( "text" ); }
  • the @functions directive

XAML

In XAML files, by default, translatable strings are extracted from i18n:Translate, i18n:Format and i18n:MultiFormat markup extensions, for example:

  • <Label Content="{i18n:Translate text}"/>
  • <Label Content="{i18n:Translate "hello, world", Context=context}"/>
  • <Label Content="{Binding Count, Converter={i18n:Format 'a dog', PluralText='{0} dogs'}}"/>

The element syntax is also supported:

<Label>
    <Label.Content>
        <i18n:Translate Context="context">another example</i18n:Translate>
    </Label.Content>
</Label>

The names of extensions and their attributes can be customized by passing additional options to the extractor, for example:

builder.add( file, extractors.xaml( text, file, {
  extensions: [ 'i18n:Translate', 'i8n:Format', 'i8n:MultiFormat' ],
  textAttribute: 'Text',
  pluralTextAttribute: 'PluralText',
  contextAttribute: 'Context',
} ) );

PHP

In PHP files, translatable strings are extracted from code blocks starting with <?php or <?=.

The order of arguments can be changed to support WordPress internationalization functions, by setting the reverseContext option to true:

builder.add( file, extractors.php( text, file, {
  string: [ '__', '_e', 'esc_html__', 'esc_html_e', 'esc_attr__', 'esc_attr_e' ],
  particularString: [ '_x', '_ex', 'esc_html_x', 'esc_attr_x' ],
  pluralString: '_n',
  particularPluralString: '_nx',
  reverseContext: true,
} ) );

Merge translations

The following function can be used to merge existing, already translated messages, with newly extracted translations:

const { mergeTranslations } = require( 'bc-gettext-utils' );

const { translations, added, updated, deleted } = mergeTranslations( existingTranslations, newTranslations );

The existingTranslations, newTranslations and the returned translations all follow the format used by gettext-parser.

In addition to the merged translations, this function returns the following information:

  • added the number of new translations which were not included in existing translations and have been added
  • update the number of translations which existed before, but the reference or plural string has been updated
  • deleted the number of existing translations which were not included in new translations and have been removed

The existing translations, translator comments and flags are preserved.

Normalize plurals

The following function can be used to normalize plurals in merged translations:

const { normalizePlurals } = require( 'bc-gettext-utils' );

const normalizedTranslations = normalizePlurals( translations, 2 );

It ensures that the plural messages contain the specified number of translated strings, and singular messages contain exactly one translated string.

Sort translations

Use the compareReference function to sort translations by file path and line number. This can be used when creating a .po file using gettext-parser:

const { compareReference } = require( 'bc-gettext-utils' );
const gettextParser = require( 'gettext-parser' );

const data = { headers, translations };
const output = gettextParser.po.compile( data, { sort: compareReference } );
1.1.1

10 months ago

1.1.0

10 months ago

1.0.5

1 year ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago