From 8b0c0b49ce241d2d33cd0dd53d4e78d8a532f37e Mon Sep 17 00:00:00 2001 From: "Amir E. Aharoni" Date: Tue, 11 Nov 2014 09:04:48 +0200 Subject: [PATCH] Add new grammar forms for language names in Russian CLDR provides translated language names. They are useful for showing names by themselves in menus and lists, but it's often problematic to add them to Russian sentences, because they need to be declined, so a message like "This page is not available in the $1 language" is hard to localize. This patch adds new cases for Russian - "languagegen", "languageprep" and "languageadverb". (The last one, as its name says, it's not actually a grammatical case, but a transformation to an adverbial expression.) This covers most of the needs for language names that MediaWiki supports. Change-Id: Ib6a0afa5c3736f8b9b2e121cd752c53ee50fad75 --- languages/classes/LanguageRu.php | 75 +++++++++++++++++- .../src/mediawiki.language/languages/ru.js | 26 +++++++ .../languages/classes/LanguageRuTest.php | 65 ++++++++++++++++ .../mediawiki/mediawiki.language.test.js | 78 +++++++++++++++++++ 4 files changed, 240 insertions(+), 4 deletions(-) diff --git a/languages/classes/LanguageRu.php b/languages/classes/LanguageRu.php index 226e313e4b..f50640ac8d 100644 --- a/languages/classes/LanguageRu.php +++ b/languages/classes/LanguageRu.php @@ -24,7 +24,9 @@ /** * Russian (русский язык) * - * You can contact Alexander Sigachov (alexander.sigachov at Googgle Mail) + * You can contact: + * Alexander Sigachov (alexander.sigachov at Googgle Mail) + * Amir E. Aharoni (amir.aharoni@mail.huji.ac.il) * * @ingroup Language */ @@ -44,9 +46,8 @@ class LanguageRu extends Language { return $wgGrammarForms['ru'][$case][$word]; } - # These rules are not perfect, but they are currently only used for Wikimedia - # site names so it doesn't matter if they are wrong sometimes. - # Just add a special case for your site name if necessary. + # These rules don't cover the whole language, and are intended only for + # names of languages and Wikimedia sites. # substr doesn't support Unicode and mb_substr has issues, # so break it to characters using preg_match_all and then use array_slice and join @@ -100,6 +101,72 @@ class LanguageRu extends Language { } elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ные' ) { $word = join( '', array_slice( $chars[0], 0, -3 ) ) . 'ных'; } + break; + case 'languagegen': # язык в родительном падеже ("(с) русского") + $suffix = join( '', array_slice( $chars[0], -3 ) ); + if ( $suffix === 'кий' ) { + $word = join( + '', + array_slice( $chars[0], 0, count( $chars[0] ) - 2 ) + ) . 'ого'; + + break; + } + + if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) { + $word = $word . 'а'; + + break; + } + + break; + case 'languageprep': # язык в предложном падеже ("(на) русском") + $suffix = join( '', array_slice( $chars[0], -3 ) ); + if ( $suffix === 'кий' ) { + $word = join( + '', + array_slice( $chars[0], 0, count( $chars[0] ) - 2 ) + ) . 'ом'; + + break; + } + + if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) { + $word = $word . 'е'; + + break; + } + + break; + case 'languageadverb': # наречие с названием языка ("по-русски") + $suffix = join( '', array_slice( $chars[0], -3 ) ); + if ( $suffix === 'кий' ) { + $word = 'по-' . join( + '', + array_slice( $chars[0], 0, count( $chars[0] ) - 1 ) + ); + + break; + } + + if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) { + $word = 'на ' . $word . 'е'; + + break; + } + + // Known particular cases of undeclinable names + // Известные несклоняемые + if ( in_array( $word, array( 'идо', 'урду', 'хинди', 'эсперанто' ) ) ) { + $word = "на $word"; + + break; + } + + // Undeclinable + // Остальные несклоняемые + $word = "на языке $word"; + break; } } diff --git a/resources/src/mediawiki.language/languages/ru.js b/resources/src/mediawiki.language/languages/ru.js index ee1d6ef2f2..ccc68f1e47 100644 --- a/resources/src/mediawiki.language/languages/ru.js +++ b/resources/src/mediawiki.language/languages/ru.js @@ -7,6 +7,7 @@ // cases. mediaWiki.language.convertGrammar = function ( word, form ) { + /*global $ */ 'use strict'; var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' ); @@ -52,6 +53,31 @@ mediaWiki.language.convertGrammar = function ( word, form ) { word = word.slice( 0, -3 ) + 'нике'; } break; + case 'languagegen': // язык в родительном падеже ("(с) русского") + if ( word.slice( -3 ) === 'кий' ) { + word = word.slice( 0, -2 ) + 'ого'; + } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) { + word = word + 'а'; + } + break; + case 'languageprep': // язык в предложном падеже ("(на) русском") + if ( word.slice( -3 ) === 'кий' ) { + word = word.slice( 0, -2 ) + 'ом'; + } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) { + word = word + 'е'; + } + break; + case 'languageadverb': // наречие с названием языка ("по-русски") + if ( word.slice( -3 ) === 'кий' ) { + word = 'по-' + word.slice( 0, -1 ); + } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) { + word = 'на ' + word + 'е'; + } else if ( $.inArray( word, [ 'идо', 'урду', 'хинди', 'эсперанто' ] ) > -1 ) { + word = 'на ' + word; + } else { + word = 'на языке ' + word; + } + break; } return word; }; diff --git a/tests/phpunit/languages/classes/LanguageRuTest.php b/tests/phpunit/languages/classes/LanguageRuTest.php index 1381afbfa9..a301479b32 100644 --- a/tests/phpunit/languages/classes/LanguageRuTest.php +++ b/tests/phpunit/languages/classes/LanguageRuTest.php @@ -110,6 +110,71 @@ class LanguageRuTest extends LanguageClassesTestCase { 'Викиданные', 'prepositional', ), + array( + 'русского', + 'русский', + 'languagegen', + ), + array( + 'немецкого', + 'немецкий', + 'languagegen', + ), + array( + 'иврита', + 'иврит', + 'languagegen', + ), + array( + 'эсперанто', + 'эсперанто', + 'languagegen', + ), + array( + 'русском', + 'русский', + 'languageprep', + ), + array( + 'немецком', + 'немецкий', + 'languageprep', + ), + array( + 'идише', + 'идиш', + 'languageprep', + ), + array( + 'эсперанто', + 'эсперанто', + 'languageprep', + ), + array( + 'по-русски', + 'русский', + 'languageadverb', + ), + array( + 'по-немецки', + 'немецкий', + 'languageadverb', + ), + array( + 'на иврите', + 'иврит', + 'languageadverb', + ), + array( + 'на эсперанто', + 'эсперанто', + 'languageadverb', + ), + array( + 'на языке гуарани', + 'гуарани', + 'languageadverb', + ), ); } } diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js index 399290ca46..4ecd480033 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js @@ -307,6 +307,84 @@ grammarForm: 'prepositional', expected: 'данных', description: 'Grammar test for prepositional case, данные -> данных' + }, + { + word: 'русский', + grammarForm: 'languagegen', + expected: 'русского', + description: 'Grammar test for languagegen case, русский -> русского' + }, + { + word: 'немецкий', + grammarForm: 'languagegen', + expected: 'немецкого', + description: 'Grammar test for languagegen case, немецкий -> немецкого' + }, + { + word: 'иврит', + grammarForm: 'languagegen', + expected: 'иврита', + description: 'Grammar test for languagegen case, иврит -> иврита' + }, + { + word: 'эсперанто', + grammarForm: 'languagegen', + expected: 'эсперанто', + description: 'Grammar test for languagegen case, эсперанто -> эсперанто' + }, + { + word: 'русский', + grammarForm: 'languageprep', + expected: 'русском', + description: 'Grammar test for languageprep case, русский -> русском' + }, + { + word: 'немецкий', + grammarForm: 'languageprep', + expected: 'немецком', + description: 'Grammar test for languageprep case, немецкий -> немецком' + }, + { + word: 'идиш', + grammarForm: 'languageprep', + expected: 'идише', + description: 'Grammar test for languageprep case, идиш -> идише' + }, + { + word: 'эсперанто', + grammarForm: 'languageprep', + expected: 'эсперанто', + description: 'Grammar test for languageprep case, эсперанто -> эсперанто' + }, + { + word: 'русский', + grammarForm: 'languageadverb', + expected: 'по-русски', + description: 'Grammar test for languageadverb case, русский -> по-русски' + }, + { + word: 'немецкий', + grammarForm: 'languageadverb', + expected: 'по-немецки', + description: 'Grammar test for languageadverb case, немецкий -> по-немецки' + }, + { + word: 'иврит', + grammarForm: 'languageadverb', + expected: 'на иврите', + description: 'Grammar test for languageadverb case, иврит -> на иврите' + }, + { + word: 'эсперанто', + grammarForm: 'languageadverb', + expected: 'на эсперанто', + description: 'Grammar test for languageadverb case, эсперанто -> на эсперанто' + }, + { + word: 'гуарани', + grammarForm: 'languageadverb', + expected: 'на языке гуарани', + description: 'Grammar test for languageadverb case, гуарани -> на языке гуарани' } ], -- 2.20.1