Compare commits

..

No commits in common. "master" and "revert-38-patch-1" have entirely different histories.

27 changed files with 1685 additions and 13857 deletions

View File

@ -53,7 +53,7 @@ module.exports = (grunt) ->
bump:
options:
files: ['package.json', 'package-lock.json', 'bower.json']
files: ['package.json', 'bower.json']
commitFiles: ['-a']
pushTo: 'origin'

View File

@ -1,6 +1,6 @@
{
"name": "pofile",
"version": "1.1.3",
"version": "1.1.0",
"authors": [
"Ruben Vermeersch <ruben@rocketeer.be>"
],

23
dist/pofile.js vendored
View File

@ -1,4 +1,8 @@
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({"pofile":[function(require,module,exports){
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
},{}],"pofile":[function(require,module,exports){
var fs = require('fs');
function trim(string) {
return string.replace(/^\s+|\s+$/g, '');
}
@ -11,6 +15,9 @@ var PO = function () {
this.items = [];
};
PO.prototype.save = function (filename, callback) {
fs.writeFile(filename, this.toString(), callback);
};
PO.prototype.toString = function () {
var lines = [];
@ -60,6 +67,16 @@ PO.prototype.toString = function () {
return lines.join('\n');
};
PO.load = function (filename, callback) {
fs.readFile(filename, 'utf-8', function (err, data) {
if (err) {
return callback(err);
}
var po = PO.parse(data);
callback(null, po);
});
};
PO.parse = function (data) {
//support both unix and windows newline formats.
data = data.replace(/\r\n/g, '\n');
@ -68,7 +85,7 @@ PO.parse = function (data) {
var headers = [];
//everything until the first 'msgid ""' is considered header
while (sections[0] && (headers.length === 0 || headers[headers.length - 1].indexOf('msgid ""') < 0)) {
if (sections[0].match(/msgid\s+"[^"]/)) {
if (sections[0].match(/msgid "[^"]/)) {
//found first real string, adding a dummy header item
headers.push('msgid ""');
} else {
@ -387,4 +404,4 @@ PO.Item.prototype.toString = function () {
module.exports = PO;
},{}]},{},["pofile"]);
},{"fs":1}]},{},["pofile"]);

2
dist/pofile.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
var fs = require('fs');
function trim(string) {
return string.replace(/^\s+|\s+$/g, '');
}
@ -10,6 +12,9 @@ var PO = function () {
this.items = [];
};
PO.prototype.save = function (filename, callback) {
fs.writeFile(filename, this.toString(), callback);
};
PO.prototype.toString = function () {
var lines = [];
@ -59,6 +64,16 @@ PO.prototype.toString = function () {
return lines.join('\n');
};
PO.load = function (filename, callback) {
fs.readFile(filename, 'utf-8', function (err, data) {
if (err) {
return callback(err);
}
var po = PO.parse(data);
callback(null, po);
});
};
PO.parse = function (data) {
//support both unix and windows newline formats.
data = data.replace(/\r\n/g, '\n');
@ -67,7 +82,7 @@ PO.parse = function (data) {
var headers = [];
//everything until the first 'msgid ""' is considered header
while (sections[0] && (headers.length === 0 || headers[headers.length - 1].indexOf('msgid ""') < 0)) {
if (sections[0].match(/msgid\s+"[^"]/)) {
if (sections[0].match(/msgid "[^"]/)) {
//found first real string, adding a dummy header item
headers.push('msgid ""');
} else {

13831
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,23 @@
{
"name": "pofile",
"description": "Parse and serialize Gettext PO files.",
"version": "1.1.5",
"version": "1.1.0",
"author": {
"name": "Vasiliy Tolstov",
"email": "v.tolstov@unistack.org",
"url": "https://unistack.org"
"name": "Ruben Vermeersch",
"email": "ruben@savanne.be",
"url": "http://savanne.be/"
},
"contributors": [
"Eyal Lewinsohn",
"Gabe Gorelick",
"Julian Bäume",
"Mike Holly",
"Sander Houttekier",
"Vasiliy Tolstov"
"Sander Houttekier"
],
"homepage": "http://github.com/unistack-org/pofile",
"homepage": "http://github.com/rubenv/pofile",
"repository": {
"type": "git",
"url": "http://github.com/unistack-org/pofile.git"
"url": "http://github.com/rubenv/pofile.git"
},
"main": "./lib/po",
"types": "./pofile.d.ts",
@ -38,15 +37,15 @@
},
"devDependencies": {
"browserify": "~14.0.0",
"coffeescript": "^2.6.1",
"grunt": "~1.3.0",
"grunt-browserify": "^5.1.0",
"grunt": "~1.0.1",
"grunt-browserify": "~5.0.0",
"grunt-bump": "0.8.0",
"grunt-contrib-clean": "^2.0.1",
"grunt-contrib-jshint": "^3.2.0",
"grunt-contrib-uglify": "^2.3.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-jscs": "^3.0.1",
"grunt-mocha-cli": "^6.0.0"
}
"grunt-contrib-clean": "~1.0.0",
"grunt-contrib-jshint": "~1.1.0",
"grunt-contrib-uglify": "~2.1.0",
"grunt-contrib-watch": "~1.0.0",
"grunt-jscs": "~3.0.1",
"grunt-mocha-cli": "~3.0.0"
},
"dependencies": {}
}

8
pofile.d.ts vendored
View File

@ -21,8 +21,10 @@ declare class Item {
public comments: string[];
public extractedComments: string[];
public flags: Record<string, boolean | undefined>;
public obsolete: boolean;
private nplurals: number;
private obsolete: boolean;
public toString(): string;
}
declare class PO {
@ -33,7 +35,11 @@ declare class PO {
public static parse(data: string): PO;
public static parsePluralForms(forms: string): PO;
public static load(fileName: string, callback: (err: NodeJS.ErrnoException, po: PO) => void): void;
public static Item: typeof Item;
public save(fileName: string, callback: (err: NodeJS.ErrnoException) => void): void;
public toString(): string;
}
export = PO

25
test/comments.js Normal file
View File

@ -0,0 +1,25 @@
var assert = require('assert');
var PO = require('..');
describe('Comments', function () {
var po;
before(function (done) {
PO.load(__dirname + '/fixtures/big.po', function (err, result) {
assert.equal(err, null);
po = result;
done();
});
});
it('Parses the po file', function () {
assert.notEqual(po, null);
});
it('Parses the comments', function () {
assert.equal(po.comments.length, 3);
assert.equal(po.comments[0], 'French translation of Link (6.x-2.9)');
assert.equal(po.comments[1], 'Copyright (c) 2011 by the French translation team');
assert.equal(po.comments[2], '');
});
});

304
test/fixtures/big.po vendored Normal file
View File

@ -0,0 +1,304 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:21+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
msgid "Title"
msgstr "Titre"
msgid "CCK"
msgstr "CCK"
msgid "Content"
msgstr "Contenu"
msgid "Link"
msgstr "Lien"
msgid "Link Target"
msgstr "Cible du Lien"
msgid "URL"
msgstr "URL"
msgid "Placeholder tokens"
msgstr "Jetons (tokens) de substitution"
msgid ""
"The following placeholder tokens can be used in both paths and titles. When "
"used in a path or title, they will be replaced with the appropriate values."
msgstr ""
"Les ébauches de jetons suivantes peuvent être utilisées à la fois dans les "
"chemins et dans les titres. Lorsqu'elles sont utilisées dans un chemin ou un "
"titre, elles seront remplacées par les valeurs appropriées."
msgid "Optional Title"
msgstr "Titre Optionnel"
msgid "Required Title"
msgstr "Titre Obligatoire"
msgid "No Title"
msgstr "Aucun Titre"
msgid "Link Title"
msgstr "Titre du Lien"
msgid "URL Display Cutoff"
msgstr "Coupure de l'Affichage de l'URL"
msgid ""
"If the user does not include a title for this link, the URL will be used as "
"the title. When should the link title be trimmed and finished with an "
"elipsis (&hellip;)? Leave blank for no limit."
msgstr ""
"Si l'utilisateur n'inclue pas de titre pour ce lien, l'URL sera utilisée en "
"tant que titre. A quel endroit le lien devra-t-il être coupé et terminé par "
"une ellipse (&hellip;) ? Laissez vide pour aucune limite."
msgid "Default (no target attribute)"
msgstr "Par Défaut (aucun attribut de cible)"
msgid "Open link in window root"
msgstr "Ouvrir le lien dans la fenêtre courante"
msgid "Open link in new window"
msgstr "Ouvrir le lien dans une nouvelle fenêtre"
msgid "Allow the user to choose"
msgstr "Autoriser l'utilisateur à choisir"
msgid "Additional CSS Class"
msgstr "Classe CSS additionnelle"
msgid "Not a valid URL."
msgstr "Cette URL n'est pas valide."
msgid "Titles are required for all links."
msgstr "Les titres sont obligatoires pour tous les liens."
msgid "Open URL in a New Window"
msgstr "Ouvril l'URL dans une Nouvelle Fenêtre"
msgid "Defines simple link field types."
msgstr "Définit les types de champs \"lien simple\"."
msgid "Link URL"
msgstr "Url du Lien"
msgid "Wildcard"
msgstr "Joker"
msgid "="
msgstr "="
msgid "Protocol"
msgstr "Protocole"
msgid "Optional URL"
msgstr "URL optionnelle"
msgid "Static Title: "
msgstr "Titre Statique : "
msgid ""
"If the link title is optional or required, a field will be displayed to the "
"end user. If the link title is static, the link will always use the same "
"title. If <a href=\"http://drupal.org/project/token\">token module</a> is "
"installed, the static title value may use any other node field as its value. "
"Static and token-based titles may include most inline XHTML tags such as "
"<em>strong</em>, <em>em</em>, <em>img</em>, <em>span</em>, etc."
msgstr ""
"Si le titre du lien est facultatif ou obligatoire, un champ sera affiché à "
"l'utilisateur final. Si le titre du lien est statique, le lien utilisera "
"toujours le même titre. Si le <a href=\"http://drupal.org/project/token"
"\">module token</a> est installé, le titre statique peut utiliser n'importe "
"quel autre champ du nœud pour sa valeur. Les titres statiques et basés sur "
"des jetons (tokens) peuvent contenir la plupart des balises XHTML en ligne, "
"telles que <em>strong</em>, <em>em</em>, <em>img</em>, <em>span</em>, etc."
msgid "Allow user-entered tokens"
msgstr "Autoriser les jetons (tokens) saisis par l'utilisateur"
msgid ""
"Checking will allow users to enter tokens in URLs and Titles on the node "
"edit form. This does not affect the field settings on this page."
msgstr ""
"Le fait de cocher cette case permettra aux utilisateurs de saisir des jetons "
"dans les URL et les Titres dans le formulaire d'édition du nœud. Ceci "
"n'affecte pas les configurations de champ sur cette page."
msgid "Rel Attribute"
msgstr "Attribut Rel"
msgid ""
"When output, this link will have this rel attribute. The most common usage "
"is <a href=\"http://en.wikipedia.org/wiki/Nofollow\">rel=&quot;nofollow&quot;"
"</a> which prevents some search engines from spidering entered links."
msgstr ""
"Quand il sera affiché, ce lien aura cet attribut rel. L'usage le plus commun "
"est <a href=\"http://fr.wikipedia.org/wiki/Nofollow\">rel=&quot;"
"nofollow&quot;</a> qui empêche certains moteurs de recherche d'aspirer les "
"liens suivis."
msgid "A default title must be provided if the title is a static value"
msgstr ""
"Un titre pas défaut doit être fourni si le titre est une valeur statique"
msgid "At least one title or URL must be entered."
msgstr "Vous devez saisir au moins un titre ou une URL."
msgid "You cannot enter a title without a link url."
msgstr "Vous ne pouvez pas saisir un titre dans une url de lien."
msgid "Title, as link (default)"
msgstr "Titre, en tant que lien (par défaut)"
msgid "URL, as link"
msgstr "URL, en tant que lien"
msgid "Short, as link with title \"Link\""
msgstr "Court, comme lien avec le titre \"Lien\""
msgid "Label, as link with label as title"
msgstr "Étiquette, comme lien avec l'étiquette comme titre"
msgid "Separate title and URL"
msgstr "Titre et URL séparés"
msgid "Validator"
msgstr "Validateur"
msgid "Is one of"
msgstr "Fait partie de"
msgid "@label title"
msgstr "Titre de @label"
msgid "@label protocol"
msgstr "Protocole de @label"
msgid "@label target"
msgstr "Cible de @label"
msgid ""
"The title to use when this argument is present; it will override the title "
"of the view and titles from previous arguments. You can use percent "
"substitution here to replace with argument titles. Use \"%1\" for the first "
"argument, \"%2\" for the second, etc."
msgstr ""
"Le titre à utiliser lorsque cet argument est présent ; il écrasera le titre "
"de la vue et les titres provenant des arguments précédents. Vous pouvez "
"utiliser ici les substitutions de pourcentage pour remplacer avec les titres "
"des arguments. Utilisez \"%1\" pour le premier argument, \"%2\" pour le "
"second, etc."
msgid "Action to take if argument is not present"
msgstr "Action à mener si l'argument est absent"
msgid ""
"If this value is received as an argument, the argument will be ignored; i.e, "
"\"all values\""
msgstr ""
"Si cette valeur est reçue comme argument, l'argument sera ignoré ; "
"correspond à \"toutes les valeurs\""
msgid "Wildcard title"
msgstr "Titre du joker"
msgid "The title to use for the wildcard in substitutions elsewhere."
msgstr ""
"Le titre à utiliser pour le joker dans les substitutions partout ailleurs."
msgid "<Basic validation>"
msgstr "<Validation basique>"
msgid "Action to take if argument does not validate"
msgstr "Actions à mener si l'argument ne passe pas la validation"
msgid ""
"The protocols displayed here are those globally available. You may add more "
"protocols by modifying the <em>filter_allowed_protocols</em> variable in "
"your installation."
msgstr ""
"Les protocoles affichés ici sont ceux disponibles de manière globale. Vous "
"pouvez ajouter plus de protocoles en modifiant la variable "
"<em>filter_allowed_protocols</em> de votre installation."
msgid "Link title"
msgstr "Titre du lien"
msgid "exposed"
msgstr "exposé"
msgid "Formatted html link"
msgstr "Lien html formaté"
msgid "Store a title, href, and attributes in the database to assemble a link."
msgstr ""
"Stocker un titre, href et des attributs dans la base de données pour les "
"assembler dans un lien."
msgid "URL, as plain text"
msgstr "URL, texte simple"
msgid "@label URL"
msgstr "URL de @label"
msgid "Validate URL"
msgstr "Valider l'URL"
msgid ""
"If checked, the URL field will be verified as a valid URL during validation."
msgstr ""
"Si coché, la validité du format de l'URL sera verifiée durant la validation."
msgid ""
"If checked, the URL field is optional and submitting a title alone will be "
"acceptable. If the URL is omitted, the title will be displayed as plain text."
msgstr ""
"Si coché, le champ URL est optionnel and soumettre un titre seul sera "
"accepté. SI l'URL est omise, le titre sera affiché en texte brut."
msgid ""
"When output, this link will have this class attribute. Multiple classes "
"should be separated by spaces."
msgstr ""
"Lors de l'affichage, le lien aura cet attribut de classe (class). Les "
"classes doivent être séparées par des espaces."
msgid "Link 'title' Attribute"
msgstr "Attribut 'title' du lien"
# Comment
msgid "Title, as plain text"
msgstr "Attribut title, en tant que texte brut"
# Empty should be adjective
msgctxt "folder display"
msgid "Empty folder"
msgstr "This folder is empty."
# Empty should be verb
msgctxt "folder action"
msgid "Empty folder"
msgstr "Make this folder empty."
msgctxt ""
"folder "
"meta"
msgid "Created Date"
msgstr "Date de création"

73
test/fixtures/c-strings.po vendored Normal file
View File

@ -0,0 +1,73 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"Language-Team: French\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"MIME-Version: 1.0\n"
"X-Generator: Poedit 1.6.2\n"
msgid "The name field must not contain characters like \" or \\"
msgstr ""
# possibility to reorder items depending on locale
#. Format of addresses
#. %1$s is the street
#. %2$s is the postal code
#. %3$s is the city
#. %4$s is the state
#. %5$s is the country
msgid ""
"%1$s\n"
"%2$s %3$s\n"
"%4$s\n"
"%5$s"
msgstr ""
# "i18"ned code
#. used in <pre> environment, so don't remove any control sequences
msgid ""
"define('some/test/module', function () {\n"
"\t'use strict';\n"
"\treturn {};\n"
"});\n"
""
msgstr ""
"define('random/test/file', function () {\n"
"\t'use strict';\n"
"\treturn {};\n"
"});\n"
""
# all one-letter escape characters
# be aware, that \a, \b, \v, \f and \r should not be used
# in i18ned messages (according to gettext tools)
# however, they should be properly parsed, anyway
msgid ""
"\a\b\t\n"
"\v\f\r"
msgstr ""
"\a\b\t\n"
"\v\f\r"
# plural text must suport \n
msgid ""
"Test.\n"
" multiline."
msgid_plural ""
"Test\n"
" multiline plural."
msgstr[0] ""
"Test.\n"
" mehrzeilig."
msgstr[1] ""
"Test.\n"
" mehrzeilig Plural."

30
test/fixtures/comment.po vendored Normal file
View File

@ -0,0 +1,30 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
#. extracted from test
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:21+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
# Translator comment
#. Extracted comment
msgid "Title, as plain text"
msgstr "Attribut title, en tant que texte brut"
#
#.
#:
#, fuzzy
msgid "Empty comment"
msgstr "Empty"

33
test/fixtures/commented.po vendored Normal file
View File

@ -0,0 +1,33 @@
msgid ""
msgstr ""
"Project-Id-Version: Test\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2014-02-17 14:11+0100\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.4\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-POOTLE-MTIME: 1390921449.000000\n"
#: .tmp/ui/settings/views/console-modal.html
msgid "{{dataLoader.data.length}} results"
msgstr "{{dataLoader.data.length}} resultaten"
#~ msgid "Add order"
#~ msgstr "Order toevoegen"
#~ # commented obsolete item
#~ #, fuzzy
#~ msgid "Commented item"
#~ msgstr "not sure"
# commented obsolete item
#, fuzzy
#~ msgid "Second commented item"
#~ msgstr "also not sure"

20
test/fixtures/fuzzy.po vendored Normal file
View File

@ -0,0 +1,20 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
#, fuzzy
msgid "Sources"
msgstr "Source"

27
test/fixtures/multi-line.po vendored Normal file
View File

@ -0,0 +1,27 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
## Plural-Forms by polish translation team to demonstrate multi-line ##
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:21+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
msgid ""
"The following placeholder tokens can be used in both paths and titles. When "
"used in a path or title, they will be replaced with the appropriate values."
msgstr ""
"Les ébauches de jetons suivantes peuvent être utilisées à la fois dans les "
"chemins et dans les titres. Lorsqu'elles sont utilisées dans un chemin ou un "
"titre, elles seront remplacées par les valeurs appropriées."

8
test/fixtures/no_header.po vendored Normal file
View File

@ -0,0 +1,8 @@
# some comment
msgid "First id, no header"
msgstr ""
msgid "A second string"
msgstr ""

30
test/fixtures/plurals/messages.po vendored Normal file
View File

@ -0,0 +1,30 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 09:59-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
# correct plurals
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] ""
msgstr[1] ""
# incorrect plurals
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr ""

37
test/fixtures/plurals/nplurals-1.po vendored Normal file
View File

@ -0,0 +1,37 @@
# Chinese translation of Link (6.x-2.9)
# Copyright (c) 2011 by the Chinese translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: Chinese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: zh_CN\n"
"X-Generator: Poedit 1.6.2\n"
# correct plurals, with translation
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] "{{$count}} thing"
# correct plurals, with no translation
msgid "1 other thing"
msgid_plural "{{$count}} other things"
msgstr[0] ""
# incorrect plurals, with translation
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr[0] "1 mistake"
msgstr[1] "{{$count}} mistakes"
# incorrect plurals, with no translation
msgid "1 other mistake"
msgid_plural "{{$count}} other mistakes"
msgstr ""

38
test/fixtures/plurals/nplurals-2.po vendored Normal file
View File

@ -0,0 +1,38 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
# correct plurals, with translation
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] "1 thing"
msgstr[1] "{{$count}} things"
# correct plurals, with no translation
msgid "1 other thing"
msgid_plural "{{$count}} other things"
msgstr[0] ""
msgstr[1] ""
# incorrect plurals, with translation
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr[0] "1 mistake"
# incorrect plurals, with no translation
msgid "1 other mistake"
msgid_plural "{{$count}} other mistakes"
msgstr ""

41
test/fixtures/plurals/nplurals-3.po vendored Normal file
View File

@ -0,0 +1,41 @@
# Polish translation of Link (6.x-2.9)
# Copyright (c) 2011 by the Polish translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: Polish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: pl_PL\n"
"X-Generator: Poedit 1.6.2\n"
# correct plurals, with translation
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] "1 thing"
msgstr[1] "{{$count}} things"
msgstr[2] "{{$count}} things"
# correct plurals, with no translation
msgid "1 other thing"
msgid_plural "{{$count}} other things"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
# incorrect plurals, with translation
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr[0] "1 mistake"
msgstr[1] "{{$count}} mistakes"
# incorrect plurals, with no translation
msgid "1 other mistake"
msgid_plural "{{$count}} other mistakes"
msgstr ""

49
test/fixtures/plurals/nplurals-6.po vendored Normal file
View File

@ -0,0 +1,49 @@
# Arabic translation of Link (6.x-2.9)
# Copyright (c) 2011 by the Arabic translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: Arabic\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: ar\n"
"X-Generator: Poedit 1.6.2\n"
# correct plurals, with translation
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] "1 thing"
msgstr[1] "{{$count}} things"
msgstr[2] "{{$count}} things"
msgstr[3] "{{$count}} things"
msgstr[4] "{{$count}} things"
msgstr[5] "{{$count}} things"
# correct plurals, with no translation
msgid "1 other thing"
msgid_plural "{{$count}} other things"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
# incorrect plurals, with translation
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr[0] "1 mistake"
msgstr[1] "{{$count}} mistakes"
msgstr[2] "{{$count}} mistakes"
# incorrect plurals, with no translation
msgid "1 other mistake"
msgid_plural "{{$count}} other mistakes"
msgstr ""

View File

@ -0,0 +1,37 @@
# Chinese translation of Link (6.x-2.9)
# Copyright (c) 2011 by the Chinese translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:59+0100\n"
"Language-Team: Chinese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: zh_CN\n"
"X-Generator: Poedit 1.6.2\n"
# correct plurals, with translation
msgid "1 thing"
msgid_plural "{{$count}} things"
msgstr[0] "1 thing"
msgstr[1] "{{$count}} things"
# correct plurals, with no translation
msgid "1 other thing"
msgid_plural "{{$count}} other things"
msgstr[0] ""
msgstr[1] ""
# incorrect plurals, with translation
msgid "1 mistake"
msgid_plural "{{$count}} mistakes"
msgstr[0] "1 mistake"
# incorrect plurals, with no translation
msgid "1 other mistake"
msgid_plural "{{$count}} other mistakes"
msgstr ""

30
test/fixtures/reference.po vendored Normal file
View File

@ -0,0 +1,30 @@
# French translation of Link (6.x-2.9)
# Copyright (c) 2011 by the French translation team
#
msgid ""
msgstr ""
"Project-Id-Version: Link (6.x-2.9)\n"
"POT-Creation-Date: 2011-12-31 23:39+0000\n"
"PO-Revision-Date: 2013-12-17 14:21+0100\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\n"
"Language: fr\n"
"X-Generator: Poedit 1.6.2\n"
# Comment
#: .tmp/crm/controllers/map.js
msgid "Title, as plain text"
msgstr "Attribut title, en tant que texte brut"
#: a
#: b
msgid "X"
msgstr "Y"
#: standard input:12 standard input:17
msgid "Z"
msgstr "ZZ"

73
test/headers.js Normal file
View File

@ -0,0 +1,73 @@
var assert = require('assert');
var PO = require('..');
describe('Headers', function () {
var po;
before(function (done) {
PO.load(__dirname + '/fixtures/big.po', function (err, result) {
assert.equal(err, null);
po = result;
done();
});
});
it('Parses the po file', function () {
assert.notEqual(po, null);
});
it('Parses headers correctly', function () {
assert.equal(po.headers['Project-Id-Version'], 'Link (6.x-2.9)');
assert.equal(po.headers['MIME-Version'], '1.0');
assert.equal(po.headers['Plural-Forms'], 'nplurals=2; plural=(n > 1);');
});
it('Parses all headers', function () {
// There are 11 headers in the .po file, but some default headers
// are defined (nr. 12 in this case is Report-Msgid-Bugs-To).
assert.equal(Object.keys(po.headers).length, 12);
});
});
describe('PO files with no headers', function () {
it('Parses an empty string', function () {
var po = PO.parse('');
assert.notEqual(po, null);
// all headers should be empty
for (var key in po.headers) {
assert.equal(po.headers[key], '');
}
assert.equal(po.items.length, 0);
});
it('Parses a minimal example', function () {
var po = PO.parse('msgid "minimal PO"\nmsgstr ""');
assert.notEqual(po, null);
// all headers should be empty
for (var key in po.headers) {
assert.equal(po.headers[key], '');
}
assert.equal(po.items.length, 1);
});
describe('advanced example', function () {
var po;
before(function (done) {
PO.load(__dirname + '/fixtures/no_header.po', function (err, result) {
assert.equal(err, null);
po = result;
done();
});
});
it('Parses the po file', function () {
assert.notEqual(po, null);
});
it('Finds all items', function () {
assert.equal(po.items.length, 2);
});
});
});

View File

@ -0,0 +1,52 @@
var assert = require('assert');
var fs = require('fs');
var PO = require('..');
describe('.parsePluralForms()', function () {
it('should return an object with empty nplurals and plural expression when there is no plural forms header', function () {
var expected = {
nplurals: undefined,
plural: undefined
};
assert.deepEqual(PO.parsePluralForms(), expected);
assert.deepEqual(PO.parsePluralForms(null), expected);
assert.deepEqual(PO.parsePluralForms(''), expected);
});
it('should return an object with nplurals and plural set to xgettext\'s default output', function () {
var pluralForms = 'nplurals=INTEGER; plural=EXPRESSION;';
var expected = {
nplurals: 'INTEGER',
plural: 'EXPRESSION'
};
var actual = PO.parsePluralForms(pluralForms);
assert.deepEqual(actual, expected);
});
it('should return an object with nplurals and plural set to typical string', function () {
var pluralForms = 'nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);';
var expected = {
nplurals: '3',
plural: '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'
};
var actual = PO.parsePluralForms(pluralForms);
assert.deepEqual(actual, expected);
});
// node-gettext stores plural forms strings with spaces. They don't appear
// to write PO files at all, but it seems prudent to handle this case
// anyway. See
// https://github.com/alexanderwallin/node-gettext/blob/v1.1.0/lib/plurals.js#L14
it('should handle spaces around assignments in plural forms string', function () {
var pluralForms = 'nplurals = 3; plural = (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);';
var expected = {
nplurals: '3',
plural: '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'
};
var actual = PO.parsePluralForms(pluralForms);
assert.deepEqual(actual, expected);
});
});

186
test/parse.js Normal file
View File

@ -0,0 +1,186 @@
var assert = require('assert');
var fs = require('fs');
var PO = require('..');
describe('Parse', function () {
it('Parses the big po file', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/big.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 70);
var item = po.items[0];
assert.equal(item.msgid, 'Title');
assert.equal(item.msgstr, 'Titre');
});
it('Handles multi-line strings', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/multi-line.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 1);
var item = po.items[0];
assert.equal(item.msgid, 'The following placeholder tokens can be used in both paths and titles. When used in a path or title, they will be replaced with the appropriate values.');
assert.equal(item.msgstr, 'Les ébauches de jetons suivantes peuvent être utilisées à la fois dans les chemins et dans les titres. Lorsqu\'elles sont utilisées dans un chemin ou un titre, elles seront remplacées par les valeurs appropriées.');
});
it('Handles multi-line headers', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/multi-line.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 1);
assert.equal(po.headers['Plural-Forms'], 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;');
});
it('Handle empty comments', function (done) {
PO.load(__dirname + '/fixtures/comment.po', function (err, po) {
assert.equal(err, null);
var item = po.items[1];
assert.equal(item.msgid, 'Empty comment');
assert.equal(item.msgstr, 'Empty');
assert.deepEqual(item.comments, ['']);
assert.deepEqual(item.extractedComments, ['']);
assert.deepEqual(item.references, ['']);
done();
});
});
it('Handles translator comments', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/comment.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 2);
var item = po.items[0];
assert.equal(item.msgid, 'Title, as plain text');
assert.equal(item.msgstr, 'Attribut title, en tant que texte brut');
assert.deepEqual(item.comments, ['Translator comment']);
});
it('Handles extracted comments', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/comment.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 2);
assert.equal(po.extractedComments.length, 1);
assert.equal(po.extractedComments[0], 'extracted from test');
var item = po.items[0];
assert.equal(item.msgid, 'Title, as plain text');
assert.equal(item.msgstr, 'Attribut title, en tant que texte brut');
assert.deepEqual(item.extractedComments, ['Extracted comment']);
});
describe('Handles string references', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/reference.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 3);
it('in simple cases', function () {
var item = po.items[0];
assert.equal(item.msgid, 'Title, as plain text');
assert.equal(item.msgstr, 'Attribut title, en tant que texte brut');
assert.deepEqual(item.comments, ['Comment']);
assert.deepEqual(item.references, ['.tmp/crm/controllers/map.js']);
});
it('with two different references', function () {
var item = po.items[1];
assert.equal(item.msgid, 'X');
assert.equal(item.msgstr, 'Y');
assert.deepEqual(item.references, ['a', 'b']);
});
it('and does not process reference items', function () {
var item = po.items[2];
assert.equal(item.msgid, 'Z');
assert.equal(item.msgstr, 'ZZ');
assert.deepEqual(item.references, ['standard input:12 standard input:17']);
});
});
it('Parses flags', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8'));
assert.notEqual(po, null);
assert.equal(po.items.length, 1);
var item = po.items[0];
assert.equal(item.msgid, 'Sources');
assert.equal(item.msgstr, 'Source');
assert.notEqual(item.flags, null);
assert.equal(item.flags.fuzzy, true);
});
it('Parses item context', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/big.po', 'utf8'));
var ambiguousItems = po.items.filter(function (item) {
return item.msgid === 'Empty folder';
});
assert.equal(ambiguousItems[0].msgctxt, 'folder display');
assert.equal(ambiguousItems[1].msgctxt, 'folder action');
});
it('Parses item multiline context', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/big.po', 'utf8'));
var item = po.items.find(function (item) {
return item.msgid === 'Created Date' && item.msgctxt === 'folder meta';
});
assert.notEqual(item, undefined);
assert.equal(item.msgctxt, 'folder meta');
});
it('Handles obsolete items', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/commented.po', 'utf8'));
assert.equal(po.items.length, 4);
var item = po.items[0];
assert.equal(item.obsolete, false);
assert.equal(item.msgid, '{{dataLoader.data.length}} results');
assert.equal(item.msgstr, '{{dataLoader.data.length}} resultaten');
item = po.items[1];
assert.equal(item.obsolete, true);
assert.equal(item.msgid, 'Add order');
assert.equal(item.msgstr, 'Order toevoegen');
item = po.items[2];
assert.equal(item.obsolete, true);
assert.equal(item.msgid, 'Commented item');
assert.equal(item.msgstr, 'not sure');
item = po.items[3];
assert.equal(item.obsolete, true);
assert.equal(item.msgid, 'Second commented item');
assert.equal(item.msgstr, 'also not sure');
});
describe('C-Strings', function () {
var po = PO.parse(fs.readFileSync(__dirname + '/fixtures/c-strings.po', 'utf8'));
it('should parse the c-strings.po file', function () {
assert.notEqual(po, null);
});
it('should extract strings containing " and \\ characters', function () {
var items = po.items.filter(function (item) {
return (/^The name field must not contain/).test(item.msgid);
});
assert.equal(items[0].msgid, 'The name field must not contain characters like " or \\');
});
it('should handle \\n characters', function () {
var item = po.items[1];
assert.equal(item.msgid, '%1$s\n%2$s %3$s\n%4$s\n%5$s');
});
it('should handle \\t characters', function () {
var item = po.items[2];
assert.equal(item.msgid, 'define(\'some/test/module\', function () {\n' +
'\t\'use strict\';\n' +
'\treturn {};\n' +
'});\n');
});
});
});

529
test/write.js Normal file
View File

@ -0,0 +1,529 @@
var assert = require('assert');
var fs = require('fs');
var PO = require('..');
function assertHasLine(str, line, doNotTrim) {
var lines = str.split('\n');
var found = false;
for (var i = 0; i < lines.length; i++) {
var lineToCompare = doNotTrim ? lines[i] : lines[i].trim();
if (lineToCompare === line) {
found = true;
break;
}
}
assert(found, 'Could not find line: ' + line);
}
function assertHasContiguousLines(str, assertedLines) {
var assertedLinesJoined = assertedLines.join('\n');
var trimmedStr = str
.split('\n')
.map(function (line) {
return line.trim();
})
.join('\n');
var found = trimmedStr.indexOf(assertedLinesJoined) !== -1;
assert(found, 'Could not find lines: \n' + assertedLinesJoined);
}
function assertDoesntHaveLine(str, line) {
var lines = str.split('\n');
var found = false;
for (var i = 0; i < lines.length; i++) {
if (lines[i].trim() === line) {
found = true;
break;
}
}
assert(!found, 'Shouldn\'t have line: ' + line);
}
describe('Write', function () {
it('write flags', function () {
var input = fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, '#, fuzzy');
});
it('write empty comment without an unecessary space', function () {
var input = fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, '#', true);
});
it('write flags only when true', function () {
var input = fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8');
var po = PO.parse(input);
// Flip flag
po.items[0].flags.fuzzy = false;
var str = po.toString();
assertDoesntHaveLine(str, '#, fuzzy');
});
it('write msgid', function () {
var input = fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, 'msgid "Sources"');
});
it('write msgstr', function () {
var input = fs.readFileSync(__dirname + '/fixtures/fuzzy.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, 'msgstr "Source"');
});
it('write translator comment', function () {
var input = fs.readFileSync(__dirname + '/fixtures/comment.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, '# Translator comment');
});
it('write extracted comment', function () {
var input = fs.readFileSync(__dirname + '/fixtures/comment.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, '#. extracted from test');
assertHasLine(str, '#. Extracted comment');
});
it('write obsolete items', function () {
var input = fs.readFileSync(__dirname + '/fixtures/commented.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, '#~ msgid "Add order"');
assertHasLine(str, '#~ msgstr "Order toevoegen"');
});
it('write obsolete items with comment', function () {
var input = fs.readFileSync(__dirname + '/fixtures/commented.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
//this is what msgcat tool of gettext does: don't print #~ for comments
assertHasLine(str, '# commented obsolete item');
assertHasLine(str, '#, fuzzy');
//items made obsolete by commenting every keyword with #~
assertHasLine(str, '#~ msgid "Commented item"');
assertHasLine(str, '#~ msgstr "not sure"');
assertHasLine(str, '#~ msgid "Second commented item"');
assertHasLine(str, '#~ msgstr "also not sure"');
});
describe('plurals', function () {
describe('nplurals INTEGER', function () {
it('should write 2 msgstrs when formatted correctly', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/messages.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] ""',
'msgstr[1] ""'
]);
});
it('should write 2 msgstrs when formatted incorrectly', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/messages.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] ""',
'msgstr[1] ""'
]);
});
});
describe('nplurals missing', function () {
it('should write 2 msgstrs when formatted correctly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-missing.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] "1 thing"',
'msgstr[1] "{{$count}} things"'
]);
});
it('should write 2 msgstrs when formatted correctly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-missing.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other things"',
'msgstr[0] ""',
'msgstr[1] ""',
]);
});
it('should keep same number of msgstrs when formatted incorrectly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-missing.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] "1 mistake"',
'',
'# incorrect plurals, with no translation'
]);
});
it('should write 2 msgstrs when formatted incorrectly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-missing.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other mistakes"',
'msgstr[0] ""',
'msgstr[1] ""'
]);
});
});
describe('nplurals=1', function () {
it('should write 1 msgstr when formatted correctly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-1.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] "{{$count}} thing"'
]);
});
it('should write 1 msgstr when formatted correctly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-1.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other things"',
'msgstr[0] ""',
'',
'# incorrect plurals, with translation'
]);
});
it('should keep same number of msgstrs when formatted incorrectly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-1.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] "1 mistake"',
'msgstr[1] "{{$count}} mistakes"'
]);
});
it('should write 1 msgstr when formatted incorrectly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-1.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other mistakes"',
'msgstr[0] ""'
]);
});
});
describe('nplurals=2', function () {
it('should write 2 msgstrs when formatted correctly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-2.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] "1 thing"',
'msgstr[1] "{{$count}} things"'
]);
});
it('should write 2 msgstrs when formatted correctly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-2.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other things"',
'msgstr[0] ""',
'msgstr[1] ""',
]);
});
it('should keep same number of msgstrs when formatted incorrectly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-2.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] "1 mistake"',
'',
'# incorrect plurals, with no translation'
]);
});
it('should write 2 msgstrs when formatted incorrectly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-2.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other mistakes"',
'msgstr[0] ""',
'msgstr[1] ""'
]);
});
});
describe('nplurals=3', function () {
it('should write 3 msgstrs when formatted correctly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-3.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] "1 thing"',
'msgstr[1] "{{$count}} things"',
'msgstr[2] "{{$count}} things"'
]);
});
it('should write 3 msgstrs when formatted correctly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-3.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other things"',
'msgstr[0] ""',
'msgstr[1] ""',
'msgstr[2] ""'
]);
});
it('should keep same number of msgstrs when formatted incorrectly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-3.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] "1 mistake"',
'msgstr[1] "{{$count}} mistakes"',
'',
'# incorrect plurals, with no translation'
]);
});
it('should write 3 msgstrs when formatted incorrectly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-3.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other mistakes"',
'msgstr[0] ""',
'msgstr[1] ""',
'msgstr[2] ""'
]);
});
});
describe('nplurals=6', function () {
it('should write 6 msgstrs when formatted correctly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-6.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} things"',
'msgstr[0] "1 thing"',
'msgstr[1] "{{$count}} things"',
'msgstr[2] "{{$count}} things"',
'msgstr[3] "{{$count}} things"',
'msgstr[4] "{{$count}} things"',
'msgstr[5] "{{$count}} things"'
]);
});
it('should write 6 msgstrs when formatted correctly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-6.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other things"',
'msgstr[0] ""',
'msgstr[1] ""',
'msgstr[2] ""',
'msgstr[3] ""',
'msgstr[4] ""',
'msgstr[5] ""'
]);
});
it('should keep same number of msgstrs when formatted incorrectly with translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-6.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} mistakes"',
'msgstr[0] "1 mistake"',
'msgstr[1] "{{$count}} mistakes"',
'msgstr[2] "{{$count}} mistakes"',
'',
'# incorrect plurals, with no translation'
]);
});
it('should write 6 msgstrs when formatted incorrectly with no translation', function () {
var input = fs.readFileSync(
__dirname + '/fixtures/plurals/nplurals-6.po', 'utf8'
);
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid_plural "{{$count}} other mistakes"',
'msgstr[0] ""',
'msgstr[1] ""',
'msgstr[2] ""',
'msgstr[3] ""',
'msgstr[4] ""',
'msgstr[5] ""'
]);
});
});
});
describe('C-Strings', function () {
it('should escape "', function () {
var item = new PO.Item();
item.msgid = '" should be written escaped';
assertHasLine(item.toString(), 'msgid "\\" should be written escaped"');
});
it('shoudl escape \\', function () {
var item = new PO.Item();
item.msgid = '\\ should be written escaped';
assertHasLine(item.toString(), 'msgid "\\\\ should be written escaped"');
});
it('should escape \\n', function () {
var item = new PO.Item();
item.msgid = '\n should be written escaped';
assertHasLine(item.toString(), 'msgid ""');
assertHasLine(item.toString(), '"\\n"');
assertHasLine(item.toString(), '" should be written escaped"');
});
it('should write identical file after parsing a file', function () {
var input = fs.readFileSync(__dirname + '/fixtures/c-strings.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assert.equal(str, input);
});
});
describe('msgctxt', function () {
it('should write context field to file', function () {
var input = fs.readFileSync(__dirname + '/fixtures/big.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasLine(str, 'msgctxt "folder action"');
});
it('should ignore omitted context field', function () {
var po = new PO();
var item = new PO.Item();
po.items.push(item);
assert.ok(po.toString().indexOf('msgctxt') < 0);
});
it('should write empty context field', function () {
var po = new PO();
var item = new PO.Item();
item.msgctxt = '';
po.items.push(item);
assert.ok(po.toString().indexOf('msgctxt') >= 0);
});
});
it('should keep the header order', function () {
var input = fs.readFileSync(__dirname + '/fixtures/big.po', 'utf8');
var po = PO.parse(input);
var str = po.toString();
assertHasContiguousLines(str, [
'msgid ""',
'msgstr ""',
'"Project-Id-Version: Link (6.x-2.9)\\n"',
'"POT-Creation-Date: 2011-12-31 23:39+0000\\n"',
'"PO-Revision-Date: 2013-12-17 14:21+0100\\n"',
'"Language-Team: French\\n"',
'"MIME-Version: 1.0\\n"',
'"Content-Type: text/plain; charset=UTF-8\\n"',
'"Content-Transfer-Encoding: 8bit\\n"',
'"Plural-Forms: nplurals=2; plural=(n > 1);\\n"',
'"Last-Translator: Ruben Vermeersch <ruben@rocketeer.be>\\n"',
'"Language: fr\\n"',
'"X-Generator: Poedit 1.6.2\\n"',
]);
});
});