From c4ad251aaa8e175f04feb81ae08b1957cde85ef1 Mon Sep 17 00:00:00 2001 From: majklvi Date: Wed, 7 Oct 2026 18:52:24 +0200 Subject: [PATCH] Use catalog plural rules for stream and file counts Route GUI counts through the shared library formatter and add plural-rule metadata to existing catalogs without changing translation text. --- Project/CMake/CLI/CMakeLists.txt | 23 +++ Source/Common/Core.cpp | 44 ++++++ Source/Common/Core.h | 2 + Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp | 12 +- Source/GUI/Qt/easyviewwidget.cpp | 12 +- Source/GUI/VCL/GUI_Main.cpp | 22 ++- Source/Resource/Language.csv | 8 + Source/Resource/Plugin/Language/README.md | 68 ++++++++ Source/Resource/Plugin/Language/ar.csv | 8 + Source/Resource/Plugin/Language/be.csv | 8 + Source/Resource/Plugin/Language/bg.csv | 8 + Source/Resource/Plugin/Language/ca.csv | 8 + Source/Resource/Plugin/Language/cs.csv | 8 + Source/Resource/Plugin/Language/da.csv | 8 + Source/Resource/Plugin/Language/de.csv | 8 + Source/Resource/Plugin/Language/en.csv | 8 + Source/Resource/Plugin/Language/es.csv | 8 + Source/Resource/Plugin/Language/eu.csv | 8 + Source/Resource/Plugin/Language/fa.csv | 8 + Source/Resource/Plugin/Language/fr.csv | 8 + Source/Resource/Plugin/Language/gl.csv | 8 + Source/Resource/Plugin/Language/gr.csv | 8 + Source/Resource/Plugin/Language/hr.csv | 8 + Source/Resource/Plugin/Language/hu.csv | 8 + Source/Resource/Plugin/Language/hy.csv | 8 + Source/Resource/Plugin/Language/id.csv | 8 + Source/Resource/Plugin/Language/it.csv | 8 + Source/Resource/Plugin/Language/ja.csv | 8 + Source/Resource/Plugin/Language/ka.csv | 8 + Source/Resource/Plugin/Language/ko.csv | 8 + Source/Resource/Plugin/Language/lt.csv | 8 + Source/Resource/Plugin/Language/nl.csv | 8 + Source/Resource/Plugin/Language/pl.csv | 8 + Source/Resource/Plugin/Language/pt-BR.csv | 8 + Source/Resource/Plugin/Language/pt.csv | 8 + Source/Resource/Plugin/Language/ro.csv | 8 + Source/Resource/Plugin/Language/ru.csv | 8 + Source/Resource/Plugin/Language/sk.csv | 8 + Source/Resource/Plugin/Language/sq.csv | 8 + Source/Resource/Plugin/Language/sv.csv | 8 + Source/Resource/Plugin/Language/th.csv | 8 + Source/Resource/Plugin/Language/tr.csv | 8 + Source/Resource/Plugin/Language/uk.csv | 8 + Source/Resource/Plugin/Language/zh-CN.csv | 8 + Source/Resource/Plugin/Language/zh-HK.csv | 8 + Source/Resource/Plugin/Language/zh-TW.csv | 8 + Source/Tests/CountFormat.cpp | 158 +++++++++++++++++++ 47 files changed, 624 insertions(+), 29 deletions(-) create mode 100644 Source/Resource/Plugin/Language/README.md create mode 100644 Source/Tests/CountFormat.cpp diff --git a/Project/CMake/CLI/CMakeLists.txt b/Project/CMake/CLI/CMakeLists.txt index 653caa5c8b..fc9df2453c 100644 --- a/Project/CMake/CLI/CMakeLists.txt +++ b/Project/CMake/CLI/CMakeLists.txt @@ -106,3 +106,26 @@ else() endif() install(TARGETS mediainfo_cli DESTINATION bin) + +option(MEDIAINFO_GUI_COUNT_TESTS "Build portable GUI count formatting tests" OFF) +if(MEDIAINFO_GUI_COUNT_TESTS) + if(NOT MEDIAINFO_CLI_STATIC) + message(FATAL_ERROR "GUI count tests require MEDIAINFO_CLI_STATIC=ON") + endif() + enable_testing() + add_executable(gui_count_format + ../../../Source/Tests/CountFormat.cpp + ../../../Source/Common/Core.cpp + ../../../Source/GUI/Common/GUI_Main_Common_Core.cpp + ../../../Source/GUI/Common/GUI_Main_Easy_Core.cpp + ../../../Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp) + target_include_directories(gui_count_format PRIVATE ../../../../ZenLib/Source) + target_compile_definitions(gui_count_format PRIVATE _UNICODE UNICODE) + set_target_properties(gui_count_format PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON) + if(MSVC) + target_compile_options(gui_count_format PRIVATE /utf-8) + endif() + target_link_libraries(gui_count_format PRIVATE mediainfo) + add_test(NAME gui_count_format COMMAND gui_count_format + "${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Resource/Plugin/Language") +endif() diff --git a/Source/Common/Core.cpp b/Source/Common/Core.cpp index c37c368334..05d27dba36 100644 --- a/Source/Common/Core.cpp +++ b/Source/Common/Core.cpp @@ -13,6 +13,7 @@ //--------------------------------------------------------------------------- #include "Core.h" #include "ZenLib/Ztring.h" +#include "ZenLib/ZtringListList.h" #include "ZenLib/File.h" //--------------------------------------------------------------------------- @@ -508,6 +509,49 @@ String Core::StreamName (stream_t StreamKind) { } } +//--------------------------------------------------------------------------- +// Use the public option interface so runtime-loaded libraries remain supported. +String Core::FormatCount(const String& Message, size_t Count, stream_t Kind, const String& Formats) +{ + Ztring KindName; + switch (Kind) + { + case MediaInfoNameSpace::Stream_Video: KindName=__T("Video"); break; + case MediaInfoNameSpace::Stream_Audio: KindName=__T("Audio"); break; + case MediaInfoNameSpace::Stream_Text: KindName=__T("Text"); break; + case MediaInfoNameSpace::Stream_Image: KindName=__T("Image"); break; + case MediaInfoNameSpace::Stream_Menu: KindName=__T("Menu"); break; + default: KindName=__T("Other"); break; + } + + Ztring Number=Ztring::ToZtring((int64u)Count); + if (MediaInfoNameSpace::MediaInfo::Option_Static(__T("Language_Format"))==__T("1")) + { + ZtringListList Request; + Request(__T("Message"))=Message; + Request(__T("Count"))=Number; + if (Message!=__T("FileCount")) + Request(__T("Kind"))=KindName; + if (Message==__T("StreamSummary")) + Request(__T("Formats"))=Formats; + // ZtringListList quotes separators and line breaks in literal metadata. + Ztring Result=MediaInfoNameSpace::MediaInfo::Option_Static(__T("Language_Format"), Request.Read()); + if (!Result.empty()) + return Result; + } + + // Older libraries cannot select the catalog's plurals: use complete English. + if (Message==__T("FileCount")) + return Number+(Count==1?__T(" file"):__T(" files")); + KindName.MakeLowerCase(); + Ztring Result=Number+__T(" ")+KindName+(Count==1?__T(" stream"):__T(" streams")); + if (Message==__T("StreamSummary")) + Result+=__T(": ")+Formats; + else if (Message==__T("StreamSummaryMore")) + Result+=__T(", see below"); + return Result; +} + String Core::Parameters () { return MediaInfoNameSpace::MediaInfo::Option_Static(__T("Info_Parameters_CSV")); } diff --git a/Source/Common/Core.h b/Source/Common/Core.h index 291a9a39b8..9f7f515179 100644 --- a/Source/Common/Core.h +++ b/Source/Common/Core.h @@ -98,6 +98,8 @@ class Core String Parameters(); String StreamName (stream_t StreamKind); size_t State_Get(); + static String FormatCount(const String& Message, size_t Count, + stream_t Kind=Stream_General, const String& Formats=String()); //Temp void Data_Prepare(); diff --git a/Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp b/Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp index dd3764903c..00a90ba7fb 100644 --- a/Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp +++ b/Source/GUI/Common/GUI_Main_Easy_Box_Core.cpp @@ -129,15 +129,11 @@ String GUI_Main_Easy_Box_Core::Text_Get() { if (C->MI->Count_Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream)>0) { - String Z1=String(C->MI->Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Measure))+__T("StreamCount"); - String Z2=String(__T(" "))+C->MI->Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text); - if (C->MI->Count_Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream)==1) - Z2+=__T(" stream");//__T(" stream1"); - else - Z2+=__T(" streams");//__T(" stream2"); - String Z3=String(C->MI->Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List")); + String FormatsKey=C->MI->Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List"); Temp+=EOL; - Temp+=(C->MI->Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream, 0, Z1)+/*Prefs->Translate(*/Z2/*)*/+/*Prefs->Translate(*/__T(": ")/*)*/+C->MI->Get(Parent_Core->FilesPos_Get(), Stream_General, 0, Z3)).c_str(); + Temp+=Core::FormatCount(__T("StreamSummary"), + C->MI->Count_Get(Parent_Core->FilesPos_Get(), (stream_t)KindOfStream), (stream_t)KindOfStream, + C->MI->Get(Parent_Core->FilesPos_Get(), Stream_General, 0, FormatsKey)); Lines++; } diff --git a/Source/GUI/Qt/easyviewwidget.cpp b/Source/GUI/Qt/easyviewwidget.cpp index c4a2f8474d..2936d8356f 100644 --- a/Source/GUI/Qt/easyviewwidget.cpp +++ b/Source/GUI/Qt/easyviewwidget.cpp @@ -94,15 +94,11 @@ QGroupBox* EasyViewWidget::createBox(stream_t StreamKind, int StreamPos) { { if (C->Count_Get(FilePos, (stream_t)KindOfStream)>0) { - String Z1=String(C->Get(FilePos, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Measure))+__T("StreamCount"); - String Z2=String(__T(" "))+C->Get(FilePos, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text); - if (C->Count_Get(FilePos, (stream_t)KindOfStream)==1) - Z2+=__T(" stream");//__T(" stream1"); - else - Z2+=__T(" streams");//__T(" stream2"); - String Z3=String(C->Get(FilePos, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List")); + String FormatsKey=C->Get(FilePos, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List"); Temp+="\n"; - Temp+=wstring2QString((C->Get(FilePos, (stream_t)KindOfStream, 0, Z1)+Z2+__T(": ")+C->Get(FilePos, Stream_General, 0, Z3))); + Temp+=wstring2QString(Core::FormatCount(__T("StreamSummary"), + C->Count_Get(FilePos, (stream_t)KindOfStream), (stream_t)KindOfStream, + C->Get(FilePos, Stream_General, 0, FormatsKey))); Lines++; } diff --git a/Source/GUI/VCL/GUI_Main.cpp b/Source/GUI/VCL/GUI_Main.cpp index 7d654733fa..2d00571fe0 100644 --- a/Source/GUI/VCL/GUI_Main.cpp +++ b/Source/GUI/VCL/GUI_Main.cpp @@ -33,6 +33,7 @@ TMainF *MainF; //--------------------------------------------------------------------------- #include "Common/Preferences.h" +#include "Common/Core.h" #include "Common/Utils.h" #ifdef MEDIAINFO_DLL_RUNTIME #include "MediaInfoDLL/MediaInfoDLL.h" @@ -1272,7 +1273,7 @@ void __fastcall TMainF::Refresh(TTabSheet *Page) Caption=(Ztring(MEDIAINFO_TITLE)+__T(" - ")+I->Get(0, Stream_General, 0, __T("CompleteName"))).c_str(); else //Plusieurs selections - Caption=(Ztring(MEDIAINFO_TITLE)+__T(" - ")+Ztring::ToZtring(FilesCount)+Prefs->Translate(__T(" file2"))).c_str(); + Caption=(Ztring(MEDIAINFO_TITLE)+__T(" - ")+Core::FormatCount(__T("FileCount"), FilesCount)).c_str(); //Configure Default options if (FilesCount>0) @@ -1802,6 +1803,7 @@ void __fastcall TMainF::M_LanguageClick(TObject *Sender) //Load Prefs->Load(Prefs_Language, Title); Translate(); + Refresh(); //Refresh global FormResize(NULL); @@ -1863,15 +1865,10 @@ void __fastcall TMainF::Page_Easy_FileChange(TObject *Sender) { if (I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind")).size()>0) { - Ztring Z1=Ztring(I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("Count")); - Ztring Z2=Ztring(__T(" "))+I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text); - Z2.MakeLowerCase(); - if (I->Count_Get(Page_Position, (stream_t)KindOfStream)>1) - Z2+=__T(" stream2"); - else - Z2+=__T(" stream1"); - Ztring Z3=Ztring(I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List")); - Page_Easy_X_List[KindOfStream]->Caption=(I->Get(Page_Position, Stream_General, 0, Z1)+Prefs->Translate(Z2)+Prefs->Translate(__T(": "))+I->Get(Page_Easy_File->ItemIndex, Stream_General, 0, Z3)).c_str(); + Ztring FormatsKey=I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("_Format_WithHint_List"); + Page_Easy_X_List[KindOfStream]->Caption=Core::FormatCount(__T("StreamSummary"), + I->Count_Get(Page_Position, (stream_t)KindOfStream), (stream_t)KindOfStream, + I->Get(Page_Position, Stream_General, 0, FormatsKey)).c_str(); } else Page_Easy_X_List[KindOfStream]->Caption=__T(""); @@ -1974,9 +1971,8 @@ void __fastcall TMainF::Page_Sheet_SheetSelectCell(TObject *Sender, System::Long Page_Sheet_X[KindOfStream]->Style=Stdctrls::csDropDownList; Page_Sheet_X[KindOfStream]->Items->Clear(); I->Option(__T("Inform"), __T("Summary")); - Ztring Z1=Ztring(I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T("Count")); - Ztring Z2=Ztring(__T(" "))+I->Get(Page_Position, (stream_t)KindOfStream, 0, __T("StreamKind"), Info_Text)+__T(" streams"); Z2.MakeLowerCase(); - Page_Sheet_X[KindOfStream]->Items->Add((I->Get(Page_Position, Stream_General, 0, Z1.c_str())+Prefs->Translate(Z2)+Prefs->Translate(__T(", "))+Prefs->Translate(__T("see below"))).c_str()); + Page_Sheet_X[KindOfStream]->Items->Add(Core::FormatCount(__T("StreamSummaryMore"), + Stream_Count, (stream_t)KindOfStream).c_str()); for (int A=0; AItems->Add(I->Get(Page_Position, (stream_t)KindOfStream, A, __T("Inform")).c_str()); Page_Sheet_X[KindOfStream]->ItemIndex=0; diff --git a/Source/Resource/Language.csv b/Source/Resource/Language.csv index 54f3cdcf79..8f3eab5647 100644 --- a/Source/Resource/Language.csv +++ b/Source/Resource/Language.csv @@ -1 +1,9 @@ Language_ISO639;ar;be;bg;ca;cs;da;de;en;es;eu;fa;fr;gl;gr;hu;id;it;ja;ko;lt;nl;pl;pt;pt-BR;ro;ru;sk;sq;sv;th;tr;uk;zh-CN;zh-HK;zh-TW;hr;hy;ka + Config_Text_PluralRules;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1 + Config_Text_PluralRule.zero;f == 0 && i == 0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + Config_Text_PluralRule.one;f == 0 && i == 1;f == 0 && i % 10 == 1 && i % 100 != 11;f == 0 && i == 1;v == 0 && i == 1;v == 0 && i == 1;(f == 0 && i == 1) || (f != 0 && i <= 1);v == 0 && i == 1;v == 0 && i == 1;f == 0 && i == 1;f == 0 && i == 1;i == 0 || (f == 0 && i == 1);i <= 1;v == 0 && i == 1;f == 0 && i == 1;f == 0 && i == 1;;v == 0 && i == 1;;;f == 0 && i % 10 == 1 && (i % 100 < 11 || i % 100 > 19);v == 0 && i == 1;v == 0 && i == 1;v == 0 && i == 1;i <= 1;v == 0 && i == 1;v == 0 && i % 10 == 1 && i % 100 != 11;v == 0 && i == 1;f == 0 && i == 1;v == 0 && i == 1;;f == 0 && i == 1;v == 0 && i % 10 == 1 && i % 100 != 11;;;;(v == 0 && i % 10 == 1 && i % 100 != 11) || (v != 0 && f % 10 == 1 && f % 100 != 11);i <= 1;f == 0 && i == 1 + Config_Text_PluralRule.two;f == 0 && i == 2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + Config_Text_PluralRule.few;f == 0 && i % 100 >= 3 && i % 100 <= 10;f == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14);;;v == 0 && i >= 2 && i <= 4;;;;;;;;;;;;;;;f == 0 && i % 10 >= 2 && (i % 100 < 11 || i % 100 > 19);;v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14);;;v != 0 || i == 0 || (i % 100 >= 1 && i % 100 <= 19);v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14);v == 0 && i >= 2 && i <= 4;;;;;v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14);;;;(v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) || (v != 0 && f % 10 >= 2 && f % 10 <= 4 && (f % 100 < 12 || f % 100 > 14));; + Config_Text_PluralRule.many;f == 0 && i % 100 >= 11;f == 0;;v == 0 && i != 0 && i % 1000000 == 0;v != 0;;;;v == 0 && i != 0 && i % 1000000 == 0;;;v == 0 && i != 0 && i % 1000000 == 0;;;;;v == 0 && i != 0 && i % 1000000 == 0;;;f != 0;;v == 0;v == 0 && i != 0 && i % 1000000 == 0;v == 0 && i != 0 && i % 1000000 == 0;;v == 0;v != 0;;;;;v == 0;;;;;; + Config_Text_PluralLegacy;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,other=2;one=1,few=2,other=3;one=1,few=2,other=3;one=1,few=2,other=3;one=1,other=2;one=1,other=2;one=1,other=2;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,other=2;one=1,other=2;one=1,few=2,other=3;one=1,other=2;one=1,other=2 + Config_Text_PluralLegacyDecimals;1;0;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;0;1;1;1;1;0;1;1;1;0;1;1 diff --git a/Source/Resource/Plugin/Language/README.md b/Source/Resource/Plugin/Language/README.md new file mode 100644 index 0000000000..c5581089df --- /dev/null +++ b/Source/Resource/Plugin/Language/README.md @@ -0,0 +1,68 @@ +# Count messages + +Count messages use the selected catalog's plural-rule metadata, independently +of the operating system locale. Older catalogs use the library's compatibility +rules selected by ` Language_ISO639`. +They are optional additions to the existing semicolon-separated CSV catalog. + +Supported key families: + +- `FileCount.`: file count in the window title. +- `StreamSummary..`: count and format list in Easy view. +- `StreamSummaryMore..`: count and navigation text in Sheet view. +- `StreamCount..`: count and stream noun only. + +Kinds are `Video`, `Audio`, `Text`, `Image`, `Other`, and `Menu`. +Categories are `zero`, `one`, `two`, `few`, `many`, and `other`. +Always provide `other`; missing categories use that message. +Only add categories needed by the language. These GUI counts are integers. + +Each pattern must contain `{count}` exactly once. `StreamSummary` also requires +`{formats}` exactly once; the other families do not accept this argument. +Translators control word order and punctuation. Write `{{` and `}}` for literal +braces. Other argument names and unmatched braces are rejected. Standard CSV +quoting applies to semicolons, quotes, and line breaks. Inserted metadata is +literal text and is never interpreted as another pattern. + +```text +StreamSummary.Audio.one;{count} audio stream: {formats} +StreamSummary.Audio.other;{count} audio streams: {formats} +FileCount.other;{count} files +``` + +Existing `stream1/2/3` and `file1/2/3` entries remain supported through a +language-specific compatibility mapping. Do not remove them. Invalid or missing +messages fall back to usable legacy translations, then to English with English +rules. Older MediaInfoLib versions without `Language_Format` use complete +English count messages; the locale-aware behavior requires the matching library. + +Catalog migrations are separate localization changes. The source fix uses +existing count forms; missing families use the complete English fallback. + +## Plural-rule metadata + +Rules and legacy-form mappings belong to the catalog. Keep metadata synchronized +between `Source/Resource/Language.csv` and the individual catalog files. +These entries are configuration data; do not translate their keys or expressions. + +```text + Config_Text_PluralRules;1 + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 +``` + +The example selects the English singular only for integer `1`. Operands are +`i` (integer part), `v` (number of visible fractional digits), and `f` (fractional +digits as an integer). Predicates may use `%`, comparisons, `&&`, `||` and +parentheses. Categories are tested in order: `zero`, `one`, `two`, `few`, `many`; +`other` is the default. Empty predicates disable a category. + +The optional legacy mapping assigns categories to existing `1/2/3` entries; +`other` supplies unspecified categories and `0` disables a legacy form. +The decimal setting permits (`1`) or disables (`0`, the default) numbered forms +for fractional notation. It does not restrict named category messages. +See MediaInfoLib's `Source/Doc/CountLocalization.md` for the complete grammar, +validation limits and fallback behavior. Missing or invalid metadata preserves +the library's existing language rules; metadata never borrows English rules +from a merged catalog. diff --git a/Source/Resource/Plugin/Language/ar.csv b/Source/Resource/Plugin/Language/ar.csv index 330c9460fe..b484a72f70 100644 --- a/Source/Resource/Plugin/Language/ar.csv +++ b/Source/Resource/Plugin/Language/ar.csv @@ -1,4 +1,12 @@ Language_ISO639;ar + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero;f == 0 && i == 0 + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two;f == 0 && i == 2 + Config_Text_PluralRule.few;f == 0 && i % 100 >= 3 && i % 100 <= 10 + Config_Text_PluralRule.many;f == 0 && i % 100 >= 11 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;Info@MediaArea.net Author_Name;Zen Author_OldNames;المترجم الأصلي diff --git a/Source/Resource/Plugin/Language/be.csv b/Source/Resource/Plugin/Language/be.csv index a9e672be71..3b4ead374a 100644 --- a/Source/Resource/Plugin/Language/be.csv +++ b/Source/Resource/Plugin/Language/be.csv @@ -1,4 +1,12 @@ Language_ISO639;be + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i % 10 == 1 && i % 100 != 11 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;f == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) + Config_Text_PluralRule.many;f == 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;dzmitry.zubialevich@gmail.comt Author_Name;Dzmitry Zubialevich Author_OldNames;Micтэр mister-sh@users.sourceforge.net diff --git a/Source/Resource/Plugin/Language/bg.csv b/Source/Resource/Plugin/Language/bg.csv index 4313281d01..2e697dd867 100644 --- a/Source/Resource/Plugin/Language/bg.csv +++ b/Source/Resource/Plugin/Language/bg.csv @@ -1,4 +1,12 @@ Language_ISO639;bg + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;ownfilmcollection@gmail.com Author_Name;ERa Author_OldNames;превод на Български diff --git a/Source/Resource/Plugin/Language/ca.csv b/Source/Resource/Plugin/Language/ca.csv index 4e632aa3c9..0215e16d4c 100644 --- a/Source/Resource/Plugin/Language/ca.csv +++ b/Source/Resource/Plugin/Language/ca.csv @@ -1,4 +1,12 @@ Language_ISO639;ca + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;sergi@octovisuals.com Author_Name;Sergi Medina Author_OldNames;BennyBeat diff --git a/Source/Resource/Plugin/Language/cs.csv b/Source/Resource/Plugin/Language/cs.csv index c33fb4385b..bce582a9c1 100644 --- a/Source/Resource/Plugin/Language/cs.csv +++ b/Source/Resource/Plugin/Language/cs.csv @@ -1,4 +1,12 @@ Language_ISO639;cs + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v == 0 && i >= 2 && i <= 4 + Config_Text_PluralRule.many;v != 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;miko.vaji@gmail.com Author_Name;Michal Várady Author_OldNames;Heavy diff --git a/Source/Resource/Plugin/Language/da.csv b/Source/Resource/Plugin/Language/da.csv index b6de7311ca..e10ecb594b 100644 --- a/Source/Resource/Plugin/Language/da.csv +++ b/Source/Resource/Plugin/Language/da.csv @@ -1,4 +1,12 @@ Language_ISO639;da + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;(f == 0 && i == 1) || (f != 0 && i <= 1) + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;l10n@joergenr.dk Author_Name;Joergen Author_OldNames;Joergen diff --git a/Source/Resource/Plugin/Language/de.csv b/Source/Resource/Plugin/Language/de.csv index 073808b468..9bc37ebe39 100644 --- a/Source/Resource/Plugin/Language/de.csv +++ b/Source/Resource/Plugin/Language/de.csv @@ -1,4 +1,12 @@ Language_ISO639;de + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;klaus.luppert@gmail.com Author_Name;Klaus Luppert Author_OldNames;harff182@arcor.de, petruscaleus@gmx.de diff --git a/Source/Resource/Plugin/Language/en.csv b/Source/Resource/Plugin/Language/en.csv index 8b6b6a90e7..e84362f397 100644 --- a/Source/Resource/Plugin/Language/en.csv +++ b/Source/Resource/Plugin/Language/en.csv @@ -1,4 +1,12 @@ Language_ISO639;en + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;Info@MediaArea.net Author_Name;Zen Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/es.csv b/Source/Resource/Plugin/Language/es.csv index 28145b8336..fcd2667351 100644 --- a/Source/Resource/Plugin/Language/es.csv +++ b/Source/Resource/Plugin/Language/es.csv @@ -1,4 +1,12 @@ Language_ISO639;es + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;damianroig53@gmail.com Author_Name;Damián Roig Author_OldNames;elega , Sergi Medina diff --git a/Source/Resource/Plugin/Language/eu.csv b/Source/Resource/Plugin/Language/eu.csv index 555ba0cf15..b5563366b3 100644 --- a/Source/Resource/Plugin/Language/eu.csv +++ b/Source/Resource/Plugin/Language/eu.csv @@ -1,4 +1,12 @@ Language_ISO639;eu + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;alexgabi@disroot.org Author_Name;Alexander Gabilondo Author_OldNames;Xabier Aramendi diff --git a/Source/Resource/Plugin/Language/fa.csv b/Source/Resource/Plugin/Language/fa.csv index 90a58e7da2..a9343eca45 100644 --- a/Source/Resource/Plugin/Language/fa.csv +++ b/Source/Resource/Plugin/Language/fa.csv @@ -1,4 +1,12 @@ Language_ISO639;fa + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;i == 0 || (f == 0 && i == 1) + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;Martik.Panosian@gmail.com Author_Name;Martik Panosian Author_OldNames;Martik diff --git a/Source/Resource/Plugin/Language/fr.csv b/Source/Resource/Plugin/Language/fr.csv index a16f0ed0c9..c7477fa0a1 100644 --- a/Source/Resource/Plugin/Language/fr.csv +++ b/Source/Resource/Plugin/Language/fr.csv @@ -1,4 +1,12 @@ Language_ISO639;fr + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;i <= 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;Info@MediaArea.net Author_Name;Zen Author_OldNames;Traducteur initial diff --git a/Source/Resource/Plugin/Language/gl.csv b/Source/Resource/Plugin/Language/gl.csv index 2b97d7860c..3b2059ccb7 100644 --- a/Source/Resource/Plugin/Language/gl.csv +++ b/Source/Resource/Plugin/Language/gl.csv @@ -1,4 +1,12 @@ Language_ISO639;gl + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;felipe_pl@yahoo.es Author_Name;Felipe Pérez Author_OldNames; diff --git a/Source/Resource/Plugin/Language/gr.csv b/Source/Resource/Plugin/Language/gr.csv index 740da43a91..9bb8e02f16 100644 --- a/Source/Resource/Plugin/Language/gr.csv +++ b/Source/Resource/Plugin/Language/gr.csv @@ -1,4 +1,12 @@ Language_ISO639;gr + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;ajinchv@csd.auth.gr Author_Name;Alexander Ntzintsvelasvili Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/hr.csv b/Source/Resource/Plugin/Language/hr.csv index 0435b7a82b..47c0f3e39c 100644 --- a/Source/Resource/Plugin/Language/hr.csv +++ b/Source/Resource/Plugin/Language/hr.csv @@ -1,4 +1,12 @@ Language_ISO639;hr + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;(v == 0 && i % 10 == 1 && i % 100 != 11) || (v != 0 && f % 10 == 1 && f % 100 != 11) + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;(v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) || (v != 0 && f % 10 >= 2 && f % 10 <= 4 && (f % 100 < 12 || f % 100 > 14)) + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;domazd@mail.ru Author_Name;Dominko Aždajić Author_OldNames;Dominko Aždajić diff --git a/Source/Resource/Plugin/Language/hu.csv b/Source/Resource/Plugin/Language/hu.csv index 0a16a35692..0e69f7b1ca 100644 --- a/Source/Resource/Plugin/Language/hu.csv +++ b/Source/Resource/Plugin/Language/hu.csv @@ -1,4 +1,12 @@ Language_ISO639;hu + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;DirektX@freemail.hu Author_Name;DirektX Author_OldNames; diff --git a/Source/Resource/Plugin/Language/hy.csv b/Source/Resource/Plugin/Language/hy.csv index 6e83ec1273..2b06e8d695 100644 --- a/Source/Resource/Plugin/Language/hy.csv +++ b/Source/Resource/Plugin/Language/hy.csv @@ -1,4 +1,12 @@ Language_ISO639;hy + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;i <= 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;hrantohanyan@mail.am Author_Name;http://haysoft.org Author_OldNames;NO diff --git a/Source/Resource/Plugin/Language/id.csv b/Source/Resource/Plugin/Language/id.csv index a794876e28..74a0b21108 100644 --- a/Source/Resource/Plugin/Language/id.csv +++ b/Source/Resource/Plugin/Language/id.csv @@ -1,4 +1,12 @@ Language_ISO639;id + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;zarambie_game@yahoo.com Author_Name;William Surya Permana Author_OldNames;Penerjemah awal diff --git a/Source/Resource/Plugin/Language/it.csv b/Source/Resource/Plugin/Language/it.csv index ef8b7bf1ee..1dbe94e27a 100644 --- a/Source/Resource/Plugin/Language/it.csv +++ b/Source/Resource/Plugin/Language/it.csv @@ -1,4 +1,12 @@ Language_ISO639;it + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;dr4k0@altervista.org - bovirus@live.it Author_Name;Dr4k0 & Bovirus Author_OldNames; diff --git a/Source/Resource/Plugin/Language/ja.csv b/Source/Resource/Plugin/Language/ja.csv index 5e927c1899..b3fe1c1602 100644 --- a/Source/Resource/Plugin/Language/ja.csv +++ b/Source/Resource/Plugin/Language/ja.csv @@ -1,4 +1,12 @@ Language_ISO639;ja + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email; Author_Name;だい(barlog), maboroshin(pc.genkaku.in) Author_OldNames;だい(barlog http://barca.daa.jp nihongoka@gmail.com), maboroshin(genkaku.in) diff --git a/Source/Resource/Plugin/Language/ka.csv b/Source/Resource/Plugin/Language/ka.csv index ecfd4a1539..ef5250094a 100644 --- a/Source/Resource/Plugin/Language/ka.csv +++ b/Source/Resource/Plugin/Language/ka.csv @@ -1,4 +1,12 @@ Language_ISO639;ka + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email; Author_Name;G Release Author_OldNames; diff --git a/Source/Resource/Plugin/Language/ko.csv b/Source/Resource/Plugin/Language/ko.csv index beac52cf54..132dfb388c 100644 --- a/Source/Resource/Plugin/Language/ko.csv +++ b/Source/Resource/Plugin/Language/ko.csv @@ -1,4 +1,12 @@ Language_ISO639;ko + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;starcodec@gmail.com Author_Name;starcodec(http://www.starcodec.com) Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/lt.csv b/Source/Resource/Plugin/Language/lt.csv index 38972a1a16..ad18db0cec 100644 --- a/Source/Resource/Plugin/Language/lt.csv +++ b/Source/Resource/Plugin/Language/lt.csv @@ -1,4 +1,12 @@ Language_ISO639;lt + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i % 10 == 1 && (i % 100 < 11 || i % 100 > 19) + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;f == 0 && i % 10 >= 2 && (i % 100 < 11 || i % 100 > 19) + Config_Text_PluralRule.many;f != 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;1 Author_Email;pauliusvenckus@gmail.com Author_Name;Paulius Author_OldNames;… diff --git a/Source/Resource/Plugin/Language/nl.csv b/Source/Resource/Plugin/Language/nl.csv index dabdfd2847..801cf071ff 100644 --- a/Source/Resource/Plugin/Language/nl.csv +++ b/Source/Resource/Plugin/Language/nl.csv @@ -1,4 +1,12 @@ Language_ISO639;nl + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;fakir@mailxxl.com Author_Name;bvv Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/pl.csv b/Source/Resource/Plugin/Language/pl.csv index ab223cd1fb..63b5dafa4b 100644 --- a/Source/Resource/Plugin/Language/pl.csv +++ b/Source/Resource/Plugin/Language/pl.csv @@ -1,4 +1,12 @@ Language_ISO639;pl + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) + Config_Text_PluralRule.many;v == 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;gregg@cdrinfo.pl Author_Name;Gregg Author_OldNames;Gregg diff --git a/Source/Resource/Plugin/Language/pt-BR.csv b/Source/Resource/Plugin/Language/pt-BR.csv index c05f618fe9..13322063ab 100644 --- a/Source/Resource/Plugin/Language/pt-BR.csv +++ b/Source/Resource/Plugin/Language/pt-BR.csv @@ -1,4 +1,12 @@ Language_ISO639;pt-BR + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;i <= 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;fga.fulvio@gmail.com Author_Name;Fúlvio Alves Author_OldNames;ReX diff --git a/Source/Resource/Plugin/Language/pt.csv b/Source/Resource/Plugin/Language/pt.csv index 2a10dd3eed..05ba74a16e 100644 --- a/Source/Resource/Plugin/Language/pt.csv +++ b/Source/Resource/Plugin/Language/pt.csv @@ -1,4 +1,12 @@ Language_ISO639;pt + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many;v == 0 && i != 0 && i % 1000000 == 0 + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;blackspirits@gmail.com Author_Name;BlackSpirits Author_OldNames;Francisco DEX, Samuel Dias diff --git a/Source/Resource/Plugin/Language/ro.csv b/Source/Resource/Plugin/Language/ro.csv index 0669a17d42..131d21d791 100644 --- a/Source/Resource/Plugin/Language/ro.csv +++ b/Source/Resource/Plugin/Language/ro.csv @@ -1,4 +1,12 @@ Language_ISO639;ro + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v != 0 || i == 0 || (i % 100 >= 1 && i % 100 <= 19) + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;1 Author_Email;cazanescu@gmail.com Author_Name;Severin Cazanescu Author_OldNames;Severin Cazanescu diff --git a/Source/Resource/Plugin/Language/ru.csv b/Source/Resource/Plugin/Language/ru.csv index 21f9c655ac..e15e1e8c4e 100644 --- a/Source/Resource/Plugin/Language/ru.csv +++ b/Source/Resource/Plugin/Language/ru.csv @@ -1,4 +1,12 @@ Language_ISO639;ru + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i % 10 == 1 && i % 100 != 11 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) + Config_Text_PluralRule.many;v == 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;solokot@gmail.com Author_Name;solokot Author_OldNames;Kazorin Sergey diff --git a/Source/Resource/Plugin/Language/sk.csv b/Source/Resource/Plugin/Language/sk.csv index 245bec7d3b..9e7ef7d172 100644 --- a/Source/Resource/Plugin/Language/sk.csv +++ b/Source/Resource/Plugin/Language/sk.csv @@ -1,4 +1,12 @@ Language_ISO639;sk + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v == 0 && i >= 2 && i <= 4 + Config_Text_PluralRule.many;v != 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email; Author_Name;Addams Author_OldNames; diff --git a/Source/Resource/Plugin/Language/sq.csv b/Source/Resource/Plugin/Language/sq.csv index 3b943e8ffd..7a32a2c741 100644 --- a/Source/Resource/Plugin/Language/sq.csv +++ b/Source/Resource/Plugin/Language/sq.csv @@ -1,4 +1,12 @@ Language_ISO639;sq + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;bgodole@gmail.com Author_Name;Besmir Godole Author_OldNames;Përkthyesi i parë diff --git a/Source/Resource/Plugin/Language/sv.csv b/Source/Resource/Plugin/Language/sv.csv index d6a020db57..aef21ba5ea 100644 --- a/Source/Resource/Plugin/Language/sv.csv +++ b/Source/Resource/Plugin/Language/sv.csv @@ -1,4 +1,12 @@ Language_ISO639;sv + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;eson57@gmail.com Author_Name;Åke Engelbrektson Author_OldNames;Yonder diff --git a/Source/Resource/Plugin/Language/th.csv b/Source/Resource/Plugin/Language/th.csv index 9b1d6a739d..94a2d01c9b 100644 --- a/Source/Resource/Plugin/Language/th.csv +++ b/Source/Resource/Plugin/Language/th.csv @@ -1,4 +1,12 @@ Language_ISO639;th + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;ประสิทธิ์ แคภูเขียว Author_Name;ประสิทธิ์ แคภูเขียว Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/tr.csv b/Source/Resource/Plugin/Language/tr.csv index ef965809fe..5b7b9dc746 100644 --- a/Source/Resource/Plugin/Language/tr.csv +++ b/Source/Resource/Plugin/Language/tr.csv @@ -1,4 +1,12 @@ Language_ISO639;tr + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;f == 0 && i == 1 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;BouRock@live.com Author_Name;Burak Yavuz (BouRock) Author_OldNames;İlk ve tek çevirmen diff --git a/Source/Resource/Plugin/Language/uk.csv b/Source/Resource/Plugin/Language/uk.csv index eb21041bc0..48cf0a2276 100644 --- a/Source/Resource/Plugin/Language/uk.csv +++ b/Source/Resource/Plugin/Language/uk.csv @@ -1,4 +1,12 @@ Language_ISO639;uk + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one;v == 0 && i % 10 == 1 && i % 100 != 11 + Config_Text_PluralRule.two; + Config_Text_PluralRule.few;v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) + Config_Text_PluralRule.many;v == 0 + Config_Text_PluralLegacy;one=1,few=2,other=3 + Config_Text_PluralLegacyDecimals;0 Author_Email;arestarh@ukr.net Author_Name;arestarh Author_OldNames;фоноскопія diff --git a/Source/Resource/Plugin/Language/zh-CN.csv b/Source/Resource/Plugin/Language/zh-CN.csv index a4da6ba65c..f72e28e4a4 100644 --- a/Source/Resource/Plugin/Language/zh-CN.csv +++ b/Source/Resource/Plugin/Language/zh-CN.csv @@ -1,4 +1,12 @@ Language_ISO639;zh-CN + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;stevenlele@outlook.com Author_Name;stevenlele Author_OldNames;chriszxl, erabbit, weiq530, nkh0472 diff --git a/Source/Resource/Plugin/Language/zh-HK.csv b/Source/Resource/Plugin/Language/zh-HK.csv index f9e3dc9ba7..66f0910765 100644 --- a/Source/Resource/Plugin/Language/zh-HK.csv +++ b/Source/Resource/Plugin/Language/zh-HK.csv @@ -1,4 +1,12 @@ Language_ISO639;zh-HK + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;cordon@gmail.com Author_Name;Kin Kwok Author_OldNames;Initial translator diff --git a/Source/Resource/Plugin/Language/zh-TW.csv b/Source/Resource/Plugin/Language/zh-TW.csv index da2b787545..451570368f 100644 --- a/Source/Resource/Plugin/Language/zh-TW.csv +++ b/Source/Resource/Plugin/Language/zh-TW.csv @@ -1,4 +1,12 @@ Language_ISO639;zh-TW + Config_Text_PluralRules;1 + Config_Text_PluralRule.zero; + Config_Text_PluralRule.one; + Config_Text_PluralRule.two; + Config_Text_PluralRule.few; + Config_Text_PluralRule.many; + Config_Text_PluralLegacy;one=1,other=2 + Config_Text_PluralLegacyDecimals;1 Author_Email;kenelin@gmail.com Author_Name;Kene Lin Author_OldNames;Initial translator diff --git a/Source/Tests/CountFormat.cpp b/Source/Tests/CountFormat.cpp new file mode 100644 index 0000000000..afc5fae124 --- /dev/null +++ b/Source/Tests/CountFormat.cpp @@ -0,0 +1,158 @@ +/* Copyright (c) MediaArea.net SARL. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license that can + * be found in the License.html file in the root of the source tree. + */ + +#include "Common/Core.h" +#include "ZenLib/Ztring.h" +#include "GUI/Common/GUI_Main_Easy_Box_Core.h" +#include "GUI/Common/GUI_Main_Easy_Core.h" +#include +#include +#include +#include + +using namespace ZenLib; +using namespace MediaInfoNameSpace; + +namespace +{ +size_t Checks=0, Failures=0; +Ztring Utf8(const std::string& Text) { return Ztring().From_UTF8(Text); } + +void Equal(const char* Label, const Ztring& Actual, const Ztring& Expected) +{ + ++Checks; + if (Actual==Expected) return; + ++Failures; + std::cerr << Label << ": expected [" << Expected.To_UTF8() + << "], got [" << Actual.To_UTF8() << "]\n"; +} + +void Check(const char* Label, bool Condition) +{ + Equal(Label, Condition?__T("true"):__T("false"), __T("true")); +} + +Ztring Catalog(const std::string& Directory, const char* Locale) +{ + std::ifstream Input((Directory+"/"+Locale+".csv").c_str(), std::ios::binary); + Check("catalog exists", Input.good()); + return Utf8(std::string(std::istreambuf_iterator(Input), std::istreambuf_iterator())); +} + +void Load(const Ztring& Catalog) { MediaInfo::Option_Static(__T("Language"), Catalog); } + +std::string Unsigned(unsigned Value) +{ + std::string Bytes(1, char(Value&0xFF)); + while (Value>>=8) Bytes.insert(Bytes.begin(), char(Value&0xFF)); + return Bytes; +} + +std::string Element(unsigned Id, const std::string& Data) +{ + unsigned Size=unsigned(Data.size()); + return Unsigned(Id)+(Size<127?std::string(1, char(0x80|Size)): + std::string(1, char(0x40|(Size>>8)))+char(Size&0xFF))+Data; +} + +std::string Integer(unsigned Id, unsigned Value) { return Element(Id, Unsigned(Value)); } + +// Six distinct mono audio tracks and ten subtitle tracks, each with one block. +// The fixture is generated locally; no external media or tools are required. +void WriteMatroska(const char* Path) +{ + std::string Header=Integer(0x4286, 1)+Integer(0x42F7, 1)+Integer(0x42F2, 4)+Integer(0x42F3, 8)+ + Element(0x4282, "matroska")+Integer(0x4287, 4)+Integer(0x4285, 2); + std::string Info=Element(0x4D80, "MediaInfo test")+Element(0x5741, "MediaInfo test"); + std::string Tracks, Blocks; + for (unsigned Track=1; Track<=16; ++Track) + { + bool Audio=Track<=6; + std::string Entry=Integer(0xD7, Track)+Integer(0x73C5, Track)+Integer(0x83, Audio?2:17)+ + Element(0x86, Audio?"A_PCM/INT/LIT":"S_TEXT/UTF8"); + if (Audio) + Entry+=Element(0xE1, Element(0xB5, std::string("\x40\xE7\x70\0\0\0\0\0", 8))+ + Integer(0x9F, 1)+Integer(0x6264, 16)); + Tracks+=Element(0xAE, Entry); + Blocks+=Element(0xA3, std::string(1, char(0x80|Track))+std::string("\0\0\x80", 3)+ + (Audio?std::string(2, '\0'):std::string("test"))); + } + std::string File=Element(0x1A45DFA3, Header)+Element(0x18538067, + Element(0x1549A966, Info)+Element(0x1654AE6B, Tracks)+Element(0x1F43B675, Integer(0xE7, 0)+Blocks)); + std::ofstream Output(Path, std::ios::binary); + Output.write(File.data(), File.size()); + Check("fixture written", Output.good()); +} +} + +int main(int argc, char** argv) +{ + if (argc!=2) + { + std::cerr << "Usage: gui_count_format \n"; + return 2; + } + Equal("formatter available", MediaInfo::Option_Static(__T("Language_Format")), __T("1")); + Ztring Czech=Catalog(argv[1], "cs"), English=Catalog(argv[1], "en"), Polish=Catalog(argv[1], "pl"); + Load(Czech); + const unsigned Counts[]={0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 14, 21, 22, 23, 24, 25, 101, 102}; + const char* Audio[]={"zvukový stream", "zvukové streamy", "zvukových streamů"}; + const char* Text[]={"textový stream", "textové streamy", "textových streamů"}; + const char* Files[]={"soubor", "soubory", "souborů"}; + for (size_t Pos=0; Pos=2 && Count<=4?1:2; + Ztring Number=Ztring::ToZtring(Count)+__T(" "); + Equal("Czech audio summary", Core::FormatCount(__T("StreamSummary"), Count, Stream_Audio, __T("PCM")), Number+Utf8(Audio[Form])+__T(": PCM")); + Equal("Czech text summary", Core::FormatCount(__T("StreamSummary"), Count, Stream_Text, __T("UTF-8")), Number+Utf8(Text[Form])+__T(": UTF-8")); + Equal("Czech Sheet summary", Core::FormatCount(__T("StreamSummaryMore"), Count, Stream_Audio), Number+Utf8(Audio[Form])+Utf8(", viz níže")); + Equal("Czech file title", Core::FormatCount(__T("FileCount"), Count), Number+Utf8(Files[Form])); + } + Equal("video kind", Core::FormatCount(__T("StreamSummary"), 6, Stream_Video, __T("AVC")), Utf8("6 streamů videa: AVC")); + Equal("image kind", Core::FormatCount(__T("StreamSummary"), 6, Stream_Image, __T("JPEG")), Utf8("6 obrazových streamů: JPEG")); + Equal("missing Czech other family uses English", Core::FormatCount(__T("StreamSummary"), 6, Stream_Other, __T("Time code")), __T("6 other streams: Time code")); + Equal("missing Czech menu family uses English", Core::FormatCount(__T("StreamSummary"), 6, Stream_Menu, __T("Chapters")), __T("6 menu streams: Chapters")); + Ztring Literal=__T("PCM; \"quoted\"\r\n{count} {{formats}} \\ tail"); + Equal("literal metadata", Core::FormatCount(__T("StreamSummary"), 6, Stream_Audio, Literal), Utf8("6 zvukových streamů: ")+Literal); + Equal("empty metadata", Core::FormatCount(__T("StreamSummary"), 6, Stream_Audio), Utf8("6 zvukových streamů: ")); + Load(Polish); + Equal("switch Czech to Polish", Core::FormatCount(__T("StreamSummary"), 22, Stream_Audio, __T("PCM")), Utf8("22 strumienie audio: PCM")); + Load(English); + Equal("switch to English singular", Core::FormatCount(__T("FileCount"), 1), __T("1 file")); + Equal("switch to English plural", Core::FormatCount(__T("FileCount"), 22), __T("22 files")); + Load(Czech); + Equal("switch back to Czech", Core::FormatCount(__T("FileCount"), 22), Utf8("22 souborů")); + Load(__T(" Language_ISO639;cs\n audio stream1; zvukový stream")); + Equal("incomplete catalog fallback", Core::FormatCount(__T("StreamSummary"), 22, Stream_Audio, __T("PCM")), __T("22 audio streams: PCM")); + Load(__T(" Language_ISO639;cs\nStreamSummary.Audio.other;{unknown}")); + Equal("malformed pattern fallback", Core::FormatCount(__T("StreamSummary"), 22, Stream_Audio, __T("PCM")), __T("22 audio streams: PCM")); + Load(__T(" Language_ISO639;cs\nStreamSummary.Audio.other;{formats}: {count} {{stop}}")); + Equal("translator word order and braces", Core::FormatCount(__T("StreamSummary"), 22, Stream_Audio, __T("PCM")), __T("PCM: 22 {stop}")); + const char* Fixture="count-format-test.mkv"; + WriteMatroska(Fixture); + { + Core C; + Check("open multi-stream fixture", C.MI->Open(Utf8(Fixture))==1); + Check("six distinct audio streams", C.MI->Count_Get(0, Stream_Audio)==6); + Check("ten distinct text streams", C.MI->Count_Get(0, Stream_Text)==10); + Equal("mono audio is not six channels", C.MI->Get(0, Stream_Audio, 0, __T("Channel(s)")), __T("1")); + GUI_Main_Easy_Core Easy(&C); + Easy.File_Pos=0; + GUI_Main_Easy_Box_Core Box(&C, &Easy, Stream_General, 0); + Load(Czech); + Ztring Summary=Box.Text_Get(); + Check("shared Easy Czech audio", Summary.find(Utf8("6 zvukových streamů: "))!=Ztring::npos); + Check("shared Easy Czech text", Summary.find(Utf8("10 textových streamů: "))!=Ztring::npos); + Load(English); + Summary=Box.Text_Get(); + Check("shared Easy language switch", Summary.find(__T("6 audio streams: "))!=Ztring::npos); + Check("shared Easy updated text", Summary.find(__T("10 text streams: "))!=Ztring::npos); + } + Check("fixture removed", std::remove(Fixture)==0); + std::cout << (Failures?"FAIL: ":"PASS: ") << Checks << " GUI count checks, " << Failures << " failures\n"; + return Failures?1:0; +}