@@ -, +, @@ --- Koha/I18N.pm | 104 +++++++++++++++++++------------ t/Koha/I18N.t | 58 +++++++++++++++++ t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.mo | Bin 0 -> 1370 bytes t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.po | 81 ++++++++++++++++++++++++ 4 files changed, 202 insertions(+), 41 deletions(-) create mode 100755 t/Koha/I18N.t create mode 100644 t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.mo create mode 100644 t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.po --- a/Koha/I18N.pm +++ a/Koha/I18N.pm @@ -26,6 +26,7 @@ use C4::Context; use Encode; use Locale::Util qw(set_locale); use Locale::Messages qw(:locale_h :libintl_h nl_putenv); +use Koha::Cache::Memory::Lite; use parent 'Exporter'; our @EXPORT = qw( @@ -44,55 +45,61 @@ our @EXPORT = qw( N__np ); -my $textdomain; +our $textdomain = 'Koha'; + +sub init { + my $cache = Koha::Cache::Memory::Lite->get_instance(); + my $cache_key = 'i18n:initialized'; + unless ($cache->get_from_cache($cache_key)) { + my $langtag = C4::Languages::getlanguage; + my @subtags = split /-/, $langtag; + my ($language, $region) = @subtags; + if ($region && length $region == 4) { + $region = $subtags[2]; + } + my $locale = set_locale(LC_ALL, $language, $region, 'utf-8'); + unless ($locale) { + set_locale(LC_MESSAGES, ''); + Locale::Messages->select_package('gettext_pp'); + $locale = $language; + if ($region) { + $locale .= '_' . $region; + } + nl_putenv("LANGUAGE=$locale"); + nl_putenv("LANG=$locale"); + nl_putenv('OUTPUT_CHARSET=utf-8'); + } -BEGIN { - $textdomain = 'Koha'; + my $directory = _base_directory(); + textdomain($textdomain); + bindtextdomain($textdomain, $directory); - my $langtag = C4::Languages::getlanguage; - my @subtags = split /-/, $langtag; - my ($language, $region) = @subtags; - if ($region && length $region == 4) { - $region = $subtags[2]; - } - my $locale = set_locale(LC_ALL, $language, $region, 'utf-8'); - unless ($locale) { - set_locale(LC_MESSAGES, 'C'); - Locale::Messages->select_package('gettext_pp'); - $locale = $language; - if ($region) { - $locale .= '_' . $region; - } - nl_putenv("LANGUAGE=$locale"); - nl_putenv("LANG=$locale"); - nl_putenv('OUTPUT_CHARSET=utf-8'); + $cache->set_in_cache($cache_key, 1); } - - my $directory = C4::Context->config('intranetdir') . '/misc/translator/po'; - textdomain($textdomain); - bindtextdomain($textdomain, $directory); } sub __ { my ($msgid) = @_; - my $text = dgettext($textdomain, $msgid); - return __decode($text); + + return _gettext(\&gettext, [ $msgid ]); } sub __x { my ($msgid, %vars) = @_; - return __expand(__($msgid), %vars); + + return _gettext(\&gettext, [ $msgid ], %vars); } sub __n { my ($msgid, $msgid_plural, $count) = @_; - my $text = dngettext($textdomain, $msgid, $msgid_plural, $count); - return __decode($text); + + return _gettext(\&ngettext, [ $msgid, $msgid_plural, $count ]); } sub __nx { my ($msgid, $msgid_plural, $count, %vars) = @_; - return __expand(__n($msgid, $msgid_plural, $count), %vars); + + return _gettext(\&ngettext, [ $msgid, $msgid_plural, $count ], %vars); } sub __xn { @@ -101,24 +108,26 @@ sub __xn { sub __p { my ($msgctxt, $msgid) = @_; - my $text = dpgettext($textdomain, $msgctxt, $msgid); - return __decode($text); + + return _gettext(\&pgettext, [ $msgctxt, $msgid ]); } sub __px { my ($msgctxt, $msgid, %vars) = @_; - return __expand(__p($msgctxt, $msgid), %vars); + + return _gettext(\&pgettext, [ $msgctxt, $msgid ], %vars); } sub __np { my ($msgctxt, $msgid, $msgid_plural, $count) = @_; - my $text = dnpgettext($textdomain, $msgctxt, $msgid, $msgid_plural, $count); - return __decode($text); + + return _gettext(\&npgettext, [ $msgctxt, $msgid, $msgid_plural, $count ]); } sub __npx { my ($msgctxt, $msgid, $msgid_plural, $count, %vars) = @_; - return __expand(__np($msgctxt, $msgid, $msgid_plural, $count), %vars); + + return _gettext(\&npgettext, [ $msgctxt, $msgid, $msgid_plural, $count], %vars); } sub N__ { @@ -137,7 +146,24 @@ sub N__np { return @_; } -sub __expand { +sub _base_directory { + return C4::Context->config('intranetdir') . '/misc/translator/po'; +} + +sub _gettext { + my ($sub, $args, %vars) = @_; + + init(); + + my $text = Encode::decode_utf8($sub->(@$args)); + if (%vars) { + $text = _expand($text, %vars); + } + + return $text; +} + +sub _expand { my ($text, %vars) = @_; my $re = join '|', map { quotemeta $_ } keys %vars; @@ -146,8 +172,4 @@ sub __expand { return $text; } -sub __decode { - return Encode::decode_utf8(shift); -} - 1; --- a/t/Koha/I18N.t +++ a/t/Koha/I18N.t @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +use Modern::Perl; +use Test::More tests => 35; +use Test::MockModule; +use FindBin qw($Bin); +use Encode; + +BEGIN { + use_ok('Koha::I18N'); +} + +my $koha_i18n = Test::MockModule->new('Koha::I18N'); +$koha_i18n->mock('_base_directory', sub { "$Bin/I18N/po" }); + +my $c4_languages = Test::MockModule->new('C4::Languages'); +$c4_languages->mock('getlanguage', sub { 'xx-XX' }); + +my @tests = ( + [ __('test') => 'test ツ' ], + [ __x('Hello {name}', name => 'World') => 'Hello World ツ' ], + [ __n('Singular', 'Plural', 0) => 'Zero ツ' ], + [ __n('Singular', 'Plural', 1) => 'Singular ツ' ], + [ __n('Singular', 'Plural', 2) => 'Plural ツ' ], + [ __n('Singular', 'Plural', 3) => 'Plural ツ' ], + [ __nx('one item', '{count} items', 0, count => 0) => 'no item ツ' ], + [ __nx('one item', '{count} items', 1, count => 1) => 'one item ツ' ], + [ __nx('one item', '{count} items', 2, count => 2) => '2 items ツ' ], + [ __nx('one item', '{count} items', 3, count => 3) => '3 items ツ' ], + [ __xn('one item', '{count} items', 0, count => 0) => 'no item ツ' ], + [ __xn('one item', '{count} items', 1, count => 1) => 'one item ツ' ], + [ __xn('one item', '{count} items', 2, count => 2) => '2 items ツ' ], + [ __xn('one item', '{count} items', 3, count => 3) => '3 items ツ' ], + [ __p('biblio', 'title') => 'title (biblio) ツ' ], + [ __p('patron', 'title') => 'title (patron) ツ' ], + [ __px('biblio', 'Remove item {id}', id => 42) => 'Remove item 42 (biblio) ツ' ], + [ __px('list', 'Remove item {id}', id => 42) => 'Remove item 42 (list) ツ' ], + [ __np('ctxt1', 'singular', 'plural', 0) => 'zero (ctxt1) ツ' ], + [ __np('ctxt1', 'singular', 'plural', 1) => 'singular (ctxt1) ツ' ], + [ __np('ctxt1', 'singular', 'plural', 2) => 'plural (ctxt1) ツ' ], + [ __np('ctxt1', 'singular', 'plural', 3) => 'plural (ctxt1) ツ' ], + [ __np('ctxt2', 'singular', 'plural', 0) => 'zero (ctxt2) ツ' ], + [ __np('ctxt2', 'singular', 'plural', 1) => 'singular (ctxt2) ツ' ], + [ __np('ctxt2', 'singular', 'plural', 2) => 'plural (ctxt2) ツ' ], + [ __np('ctxt2', 'singular', 'plural', 3) => 'plural (ctxt2) ツ' ], + [ __npx('biblio', 'one item', '{count} items', 0, count => 0) => 'no item (biblio) ツ' ], + [ __npx('biblio', 'one item', '{count} items', 1, count => 1) => 'one item (biblio) ツ' ], + [ __npx('biblio', 'one item', '{count} items', 2, count => 2) => '2 items (biblio) ツ' ], + [ __npx('biblio', 'one item', '{count} items', 3, count => 3) => '3 items (biblio) ツ' ], + [ __npx('list', 'one item', '{count} items', 0, count => 0) => 'no item (list) ツ' ], + [ __npx('list', 'one item', '{count} items', 1, count => 1) => 'one item (list) ツ' ], + [ __npx('list', 'one item', '{count} items', 2, count => 2) => '2 items (list) ツ' ], + [ __npx('list', 'one item', '{count} items', 3, count => 3) => '3 items (list) ツ' ], +); + +foreach my $test (@tests) { + is($test->[0], decode_utf8($test->[1]), $test->[1]); +} --- a/t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.po +++ a/t/Koha/I18N/po/xx_XX/LC_MESSAGES/Koha.po @@ -0,0 +1,81 @@ +# PO file for tests +# Copyright (C) 2017 BibLibre +# This file is distributed under the same license as the Koha package. +# Julian Maurice \n" +"Language-Team: xx \n" +"Language: xx_XX\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==0 ? 0 : n==1 ? 1 : 2);\n" + +msgid "test" +msgstr "test ツ" + +msgid "Hello {name}" +msgstr "Hello {name} ツ" + +msgid "Singular" +msgid_plural "Plural" +msgstr[0] "Zero ツ" +msgstr[1] "Singular ツ" +msgstr[2] "Plural ツ" + +msgid "one item" +msgid_plural "{count} items" +msgstr[0] "no item ツ" +msgstr[1] "one item ツ" +msgstr[2] "{count} items ツ" + +msgctxt "biblio" +msgid "title" +msgstr "title (biblio) ツ" + +msgctxt "patron" +msgid "title" +msgstr "title (patron) ツ" + +msgctxt "biblio" +msgid "Remove item {id}" +msgstr "Remove item {id} (biblio) ツ" + +msgctxt "list" +msgid "Remove item {id}" +msgstr "Remove item {id} (list) ツ" + +msgctxt "ctxt1" +msgid "singular" +msgid_plural "plural" +msgstr[0] "zero (ctxt1) ツ" +msgstr[1] "singular (ctxt1) ツ" +msgstr[2] "plural (ctxt1) ツ" + +msgctxt "ctxt2" +msgid "singular" +msgid_plural "plural" +msgstr[0] "zero (ctxt2) ツ" +msgstr[1] "singular (ctxt2) ツ" +msgstr[2] "plural (ctxt2) ツ" + +msgctxt "biblio" +msgid "one item" +msgid_plural "{count} items" +msgstr[0] "no item (biblio) ツ" +msgstr[1] "one item (biblio) ツ" +msgstr[2] "{count} items (biblio) ツ" + +msgctxt "list" +msgid "one item" +msgid_plural "{count} items" +msgstr[0] "no item (list) ツ" +msgstr[1] "one item (list) ツ" +msgstr[2] "{count} items (list) ツ" --