npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bc-gettext-utils

v1.1.1

Published

Bulletcode gettext utilities

Downloads

22

Readme

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 } );