From ef6ddd9c834b63c5f81f782520cdae53836ca694 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Wed, 13 May 2015 14:36:03 +0300 Subject: [PATCH 01/55] ReSharper settings update. --- src/NGettext.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NGettext.sln.DotSettings b/src/NGettext.sln.DotSettings index a564176..c41fe1e 100644 --- a/src/NGettext.sln.DotSettings +++ b/src/NGettext.sln.DotSettings @@ -1,6 +1,8 @@  DO_NOT_SHOW + 15 System + On$object$$event$ <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> From 16fbd32a6f4888f8d48d92515439d1fe9f86ca61 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Wed, 13 May 2015 17:33:43 +0300 Subject: [PATCH 02/55] Small code style and typo fixes. --- src/NGettext/Catalog.cs | 12 ++++++------ src/NGettext/Loaders/MoFileParser.cs | 23 ++++++++++++++--------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index f46e2c9..eafa22f 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -81,7 +81,7 @@ public Catalog(string domain, string localeDir) { try { - this.Load(CultureInfo, domain, localeDir); + this.Load(this.CultureInfo, domain, localeDir); } catch (FileNotFoundException exception) { @@ -101,7 +101,7 @@ public Catalog(string domain, string localeDir, CultureInfo cultureInfo) { try { - this.Load(CultureInfo, domain, localeDir); + this.Load(this.CultureInfo, domain, localeDir); } catch (FileNotFoundException exception) { @@ -159,16 +159,16 @@ public void Load(Stream moStream, Encoding encoding = null) private string _FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) { - var posibleFiles = new [] { + var possibleFiles = new [] { this._GetFileName(localeDir, domain, cultureInfo.Name), this._GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) }; - foreach (var posibleFilePath in posibleFiles) + foreach (var possibleFilePath in possibleFiles) { - if (File.Exists(posibleFilePath)) + if (File.Exists(possibleFilePath)) { - return posibleFilePath; + return possibleFilePath; } } diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index 40da2c2..66d10f6 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -12,6 +12,11 @@ namespace NGettext.Loaders /// public class MoFileParser { + /// + /// MO file format magic number. + /// + public const uint MO_FILE_MAGIC = 0x950412de; + private struct StringOffsetTable { public int Length; @@ -49,9 +54,9 @@ public Dictionary GetTranslations(Stream stream) } var reader = new BinaryReader(stream); - var magicNumber = reader.ReadUInt32(); - - if (magicNumber != 0x950412de) + var magicNumber = reader.ReadUInt32(); + + if (magicNumber != MO_FILE_MAGIC) { throw new ArgumentException("Invalid stream: can not find MO file magic number."); } @@ -66,7 +71,7 @@ public Dictionary GetTranslations(Stream stream) var stringCount = reader.ReadInt32(); var originalTableOffset = reader.ReadInt32(); - var translationlTableOffset = reader.ReadInt32(); + var translationTableOffset = reader.ReadInt32(); // We don't support hash tables and system dependent segments. @@ -75,7 +80,7 @@ public Dictionary GetTranslations(Stream stream) var originalTable = new StringOffsetTable[stringCount]; - var translationlTable = new StringOffsetTable[stringCount]; + var translationTable = new StringOffsetTable[stringCount]; Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); @@ -86,11 +91,11 @@ public Dictionary GetTranslations(Stream stream) originalTable[i].Offset = reader.ReadInt32(); } - reader.BaseStream.Seek(translationlTableOffset, SeekOrigin.Begin); + reader.BaseStream.Seek(translationTableOffset, SeekOrigin.Begin); for (int i = 0; i < stringCount; i++) { - translationlTable[i].Length = reader.ReadInt32(); - translationlTable[i].Offset = reader.ReadInt32(); + translationTable[i].Length = reader.ReadInt32(); + translationTable[i].Offset = reader.ReadInt32(); } @@ -99,7 +104,7 @@ public Dictionary GetTranslations(Stream stream) for (int i = 0; i < stringCount; i++) { var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); - var translatedStrings = this._ReadStrings(reader, translationlTable[i].Offset, translationlTable[i].Length); + var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); dict.Add(originalStrings[0], translatedStrings); } From 36e8f202194e0d66e0d47d39e81e520e9f51ac3c Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Wed, 13 May 2015 17:47:37 +0300 Subject: [PATCH 03/55] EOL Conversion. --- .gitignore | 82 +-- LICENSE | 42 +- NGettext.build | 324 +++++----- README.md | 376 ++++++------ build.conf.dist | 32 +- doc/examples/T.cs | 110 ++-- src/NGettext.Tests/BaseCatalogTest.cs | 394 ++++++------ src/NGettext.Tests/CatalogTest.cs | 132 ++-- .../Loaders/MoFileParserTest.cs | 68 +-- src/NGettext.Tests/NGettext.Tests.csproj | 172 +++--- .../Plural/PluralFormProcessorTest.cs | 294 ++++----- src/NGettext.Tests/Properties/AssemblyInfo.cs | 72 +-- src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs | 32 +- src/NGettext.sln | 56 +- src/NGettext.sln.DotSettings | 26 +- src/NGettext/BaseCatalog.cs | 420 ++++++------- src/NGettext/Catalog.cs | 374 ++++++------ src/NGettext/ICatalog.cs | 178 +++--- src/NGettext/Loaders/MoFileParser.cs | 238 ++++---- src/NGettext/NGettext.csproj | 122 ++-- src/NGettext/Plural/PluralFormProcessor.cs | 568 +++++++++--------- src/NGettext/Properties/AssemblyInfo.cs | 48 +- 22 files changed, 2080 insertions(+), 2080 deletions(-) diff --git a/.gitignore b/.gitignore index efa5b9d..3dafac3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,41 +1,41 @@ - -###### Editor files -*~ -*.bak -*.orig -*.pidb -*.suo -*.user -*.userprefs -*.usertasks -*.resources -*.vs10x -*_ReSharper.* - - -###### Binary files -[Bb]in -[Oo]bj -*.cache -*.sln.proj -*.nupkg - - -###### Custom NAnt configuration -/build.conf - - -###### Automatic generated documentation and report files -doc/generated/* -doc/reports/* - - -###### Other files -dep/src/* -src/packages/* -NGettext.snk - - -###### OS generated files -Thumbs.db -.DS_Store* + +###### Editor files +*~ +*.bak +*.orig +*.pidb +*.suo +*.user +*.userprefs +*.usertasks +*.resources +*.vs10x +*_ReSharper.* + + +###### Binary files +[Bb]in +[Oo]bj +*.cache +*.sln.proj +*.nupkg + + +###### Custom NAnt configuration +/build.conf + + +###### Automatic generated documentation and report files +doc/generated/* +doc/reports/* + + +###### Other files +dep/src/* +src/packages/* +NGettext.snk + + +###### OS generated files +Thumbs.db +.DS_Store* diff --git a/LICENSE b/LICENSE index 09f71cd..1d03b9b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ - -Copyright (c) 2012 Neris Ereptoris (www.neris.ws) - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Copyright (c) 2012 Neris Ereptoris (www.neris.ws) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/NGettext.build b/NGettext.build index a3bd167..062bda3 100644 --- a/NGettext.build +++ b/NGettext.build @@ -1,163 +1,163 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 06b290b..c0b2786 100644 --- a/README.md +++ b/README.md @@ -1,188 +1,188 @@ -NGettext [![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext) -======== - -Copyright (C) 2012 Neris Ereptoris . - - -Just another one GNU/Gettext implementation for .NET. -Requires Microsoft .NET Framework 2.0 or higher or Mono. - -This implementation loads translations directly from gettext *.mo files (no need to compile a satellite assembly) and can handle multiple translation domains and multiple locales in one application instance. - -NGettext currently not supports *.mo file headers (stored in mo file plural formulas, encoding, etc.). -It uses precompiled plural formulas and supports custom plural formulas passed through API. -It only supports little-endian MO files (witch produce most of popular platforms). - - - -Why not others? ---------------- - -**Why not Mono.Unix.Catalog?** -Mono's Catalog is just a bindings to three native functions (bindtextdomain, gettext, and ngettext). It does not support multiple domains/locales and contexts. It is not cross-patform, it have problems with Windows OS. - - -**Why not GNU.Gettext?** -It uses satellite assemblies as a translation files and does not support multiple locales in one application instance. -It's hard to build and maintain translation files and change locale inside your application. - -**So why NGettext?** -* NGettext is fully cross-platform as it don't uses any native or managed 3rd-party libraries. -* NGettext supports multiple domains. You can separate translation files for each of your application's module or plugin. -* NGettext supports multiple locales in one application instance and gives really simple API to choose locale of your application. - You don't even need to care about locales of your application's threads. -* NGettext loads translations from *.mo files. You can even load translations from specified file or stream. -* NGettext supports message contexts. -* NGettext provides nice and simple API for translation. - - -Building from the sources -------------------------- - -### Building on Linux - - Requirements: - [Mono](http://www.go-mono.com/mono-downloads/download.html), - [NAnt](http://nant.sourceforge.net/). - - Execute the `nant` command in the project directory to build project with the Release configuration. - -### Building on Windows - - Requirements: - Microsoft .NET Framework 2.0 or higher, - [NAnt](http://nant.sourceforge.net/). - - Just run `build.bat` to build project with the Release configuration. - - - -Installation and usage ----------------------- - -All you need to do is just install a [NuGet package](https://www.nuget.org/packages/NGettext/): -``` -PM> Install-Package NGettext -``` - -Alternatively you can download [compiled binaries](https://github.com/neris/NGettext/releases) or the [source code](https://github.com/neris/NGettext) and add a reference to `NGettext.dll` or `NGettext.csproj` to your project. - - -Now you can use NGettext in your code: -```csharp - using NGettext; -``` -```csharp - // This will load translations from "./locale//LC_MESSAGES/Example.mo" - ICatalog catalog = new Catalog("Example", "./locale"); - - // or - - // This will load translations from "./locale/ru_RU/LC_MESSAGES/Example.mo" - ICatalog catalog = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("ru-RU")); -``` -```csharp - Console.WriteLine(catalog.GetString("Hello, World!")); // will translate "Hello, World!" using loaded translations - Console.WriteLine(catalog.GetString("Hello, {0}!", "World")); // String.Format support -``` - - - -### Plural forms - -```csharp - catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", count); - // Returns (for en_US locale): - // "You have {0} apple." for count = 1 - // "You have {0} apples." otherwise - - - catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", 5, 5); - // Returns translated plural massage: "You have 5 apples." (for en_US locale) - // First 5 used in plural forms determination; second in String.Format method -``` - - - -### Contexts - -```csharp - catalog.GetParticularString("Menu|File|", "Open"); // will translate message "Open" using context "Menu|File|" - catalog.GetParticularString("Menu|Project|", "Open"); // will translate message "Open" using context "Menu|Project|" -``` - - - -### Multiple locales and domains in one application instance - -```csharp - // "./locale/en_US/LC_MESSAGES/Example.mo" - ICatalog example_en = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("en-US")); - - // "./locale/fr/LC_MESSAGES/Example.mo" - ICatalog example_fr = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("fr")); - - // "./locale//LC_MESSAGES/AnotherDomainName.mo" - ICatalog anotherDomain = new Catalog("AnotherDomainName", "./locale"); -``` - - - -### Direct MO file loading - -```csharp - Stream moFileStream = File.OpenRead("path/to/domain.mo"); - ICatalog catalog = new Catalog(moFileStream); -``` - - - -### Custom plural formulas - -```csharp - catalog.PluralForm.SetCustomFormula(cultureInfo, n => ( n == 1 ? 0 : 1 )); -``` - - - -Debugging ---------- - -Debug version of the NGettext binary outputs debug messages to System.Diagnostics.Trace. -You can register trace listeners to see NGettext debug messages. -Please note that Release version of the NGettext binary does not produse any trace messages. - -```csharp - Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); -``` - - - -Shorter syntax --------------- - -In `doc/examples/T.cs` you can see an example of shorter syntax creation for NGettext: -```csharp - T._("Hello, World!"); // GetString - T._n("You have {0} apple.", "You have {0} apples.", count, count); // GetPluralString - T._p("Context", "Hello, World!"); // GetParticularString - T._pn("Context", "You have {0} apple.", "You have {0} apples.", count, count); // GetParticularPluralString -``` - - - -Poedit compatibility --------------------- - -For [Poedit](http://www.poedit.net/) compatibility, you need to specify plural form in your *.pot file header, even for english language: -``` - "Plural-Forms: nplurals=2; plural=n != 1;\n" -``` - -And a keywords list: -``` - "X-Poedit-KeywordsList: GetString;GetPluralString:1,2;GetParticularString:1c,2;GetParticularPluralString:1c,2,3;_;_n:1,2;_p:1c,2;_pn:1c,2,3\n" -``` - - - +NGettext [![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext) +======== + +Copyright (C) 2012 Neris Ereptoris . + + +Just another one GNU/Gettext implementation for .NET. +Requires Microsoft .NET Framework 2.0 or higher or Mono. + +This implementation loads translations directly from gettext *.mo files (no need to compile a satellite assembly) and can handle multiple translation domains and multiple locales in one application instance. + +NGettext currently not supports *.mo file headers (stored in mo file plural formulas, encoding, etc.). +It uses precompiled plural formulas and supports custom plural formulas passed through API. +It only supports little-endian MO files (witch produce most of popular platforms). + + + +Why not others? +--------------- + +**Why not Mono.Unix.Catalog?** +Mono's Catalog is just a bindings to three native functions (bindtextdomain, gettext, and ngettext). It does not support multiple domains/locales and contexts. It is not cross-patform, it have problems with Windows OS. + + +**Why not GNU.Gettext?** +It uses satellite assemblies as a translation files and does not support multiple locales in one application instance. +It's hard to build and maintain translation files and change locale inside your application. + +**So why NGettext?** +* NGettext is fully cross-platform as it don't uses any native or managed 3rd-party libraries. +* NGettext supports multiple domains. You can separate translation files for each of your application's module or plugin. +* NGettext supports multiple locales in one application instance and gives really simple API to choose locale of your application. + You don't even need to care about locales of your application's threads. +* NGettext loads translations from *.mo files. You can even load translations from specified file or stream. +* NGettext supports message contexts. +* NGettext provides nice and simple API for translation. + + +Building from the sources +------------------------- + +### Building on Linux + + Requirements: + [Mono](http://www.go-mono.com/mono-downloads/download.html), + [NAnt](http://nant.sourceforge.net/). + + Execute the `nant` command in the project directory to build project with the Release configuration. + +### Building on Windows + + Requirements: + Microsoft .NET Framework 2.0 or higher, + [NAnt](http://nant.sourceforge.net/). + + Just run `build.bat` to build project with the Release configuration. + + + +Installation and usage +---------------------- + +All you need to do is just install a [NuGet package](https://www.nuget.org/packages/NGettext/): +``` +PM> Install-Package NGettext +``` + +Alternatively you can download [compiled binaries](https://github.com/neris/NGettext/releases) or the [source code](https://github.com/neris/NGettext) and add a reference to `NGettext.dll` or `NGettext.csproj` to your project. + + +Now you can use NGettext in your code: +```csharp + using NGettext; +``` +```csharp + // This will load translations from "./locale//LC_MESSAGES/Example.mo" + ICatalog catalog = new Catalog("Example", "./locale"); + + // or + + // This will load translations from "./locale/ru_RU/LC_MESSAGES/Example.mo" + ICatalog catalog = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("ru-RU")); +``` +```csharp + Console.WriteLine(catalog.GetString("Hello, World!")); // will translate "Hello, World!" using loaded translations + Console.WriteLine(catalog.GetString("Hello, {0}!", "World")); // String.Format support +``` + + + +### Plural forms + +```csharp + catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", count); + // Returns (for en_US locale): + // "You have {0} apple." for count = 1 + // "You have {0} apples." otherwise + + + catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", 5, 5); + // Returns translated plural massage: "You have 5 apples." (for en_US locale) + // First 5 used in plural forms determination; second in String.Format method +``` + + + +### Contexts + +```csharp + catalog.GetParticularString("Menu|File|", "Open"); // will translate message "Open" using context "Menu|File|" + catalog.GetParticularString("Menu|Project|", "Open"); // will translate message "Open" using context "Menu|Project|" +``` + + + +### Multiple locales and domains in one application instance + +```csharp + // "./locale/en_US/LC_MESSAGES/Example.mo" + ICatalog example_en = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("en-US")); + + // "./locale/fr/LC_MESSAGES/Example.mo" + ICatalog example_fr = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("fr")); + + // "./locale//LC_MESSAGES/AnotherDomainName.mo" + ICatalog anotherDomain = new Catalog("AnotherDomainName", "./locale"); +``` + + + +### Direct MO file loading + +```csharp + Stream moFileStream = File.OpenRead("path/to/domain.mo"); + ICatalog catalog = new Catalog(moFileStream); +``` + + + +### Custom plural formulas + +```csharp + catalog.PluralForm.SetCustomFormula(cultureInfo, n => ( n == 1 ? 0 : 1 )); +``` + + + +Debugging +--------- + +Debug version of the NGettext binary outputs debug messages to System.Diagnostics.Trace. +You can register trace listeners to see NGettext debug messages. +Please note that Release version of the NGettext binary does not produse any trace messages. + +```csharp + Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); +``` + + + +Shorter syntax +-------------- + +In `doc/examples/T.cs` you can see an example of shorter syntax creation for NGettext: +```csharp + T._("Hello, World!"); // GetString + T._n("You have {0} apple.", "You have {0} apples.", count, count); // GetPluralString + T._p("Context", "Hello, World!"); // GetParticularString + T._pn("Context", "You have {0} apple.", "You have {0} apples.", count, count); // GetParticularPluralString +``` + + + +Poedit compatibility +-------------------- + +For [Poedit](http://www.poedit.net/) compatibility, you need to specify plural form in your *.pot file header, even for english language: +``` + "Plural-Forms: nplurals=2; plural=n != 1;\n" +``` + +And a keywords list: +``` + "X-Poedit-KeywordsList: GetString;GetPluralString:1,2;GetParticularString:1c,2;GetParticularPluralString:1c,2,3;_;_n:1,2;_p:1c,2;_pn:1c,2,3\n" +``` + + + diff --git a/build.conf.dist b/build.conf.dist index 5858f15..b7bda88 100644 --- a/build.conf.dist +++ b/build.conf.dist @@ -1,17 +1,17 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/examples/T.cs b/doc/examples/T.cs index b68cd98..c4bbb91 100644 --- a/doc/examples/T.cs +++ b/doc/examples/T.cs @@ -1,56 +1,56 @@ -using System; -using NGettext; - -// -// Usage: -// T._("Hello, World!"); -// T._n("You have {0} apple.", "You have {0} apples.", count, count); -// -namespace Example -{ - internal class T - { - private static readonly ICatalog _Catalog = new Catalog("Example", "./locale"); - - - public static string _(string text) - { - return _Catalog.GetString(text); - } - - public static string _(string text, params object[] args) - { - return _Catalog.GetString(text, args); - } - - public static string _n(string text, string pluralText, long n) - { - return _Catalog.GetPluralString(text, pluralText, n); - } - - public static string _n(string text, string pluralText, long n, params object[] args) - { - return _Catalog.GetPluralString(text, pluralText, n, args); - } - - public static string _p(string context, string text) - { - return _Catalog.GetParticularString(context, text); - } - - public static string _p(string context, string text, params object[] args) - { - return _Catalog.GetParticularString(context, text, args); - } - - public static string _pn(string context, string text, string pluralText, long n) - { - return _Catalog.GetParticularPluralString(context, text, pluralText, n); - } - - public static string _pn(string context, string text, string pluralText, long n, params object[] args) - { - return _Catalog.GetParticularPluralString(context, text, pluralText, n, args); - } - } +using System; +using NGettext; + +// +// Usage: +// T._("Hello, World!"); +// T._n("You have {0} apple.", "You have {0} apples.", count, count); +// +namespace Example +{ + internal class T + { + private static readonly ICatalog _Catalog = new Catalog("Example", "./locale"); + + + public static string _(string text) + { + return _Catalog.GetString(text); + } + + public static string _(string text, params object[] args) + { + return _Catalog.GetString(text, args); + } + + public static string _n(string text, string pluralText, long n) + { + return _Catalog.GetPluralString(text, pluralText, n); + } + + public static string _n(string text, string pluralText, long n, params object[] args) + { + return _Catalog.GetPluralString(text, pluralText, n, args); + } + + public static string _p(string context, string text) + { + return _Catalog.GetParticularString(context, text); + } + + public static string _p(string context, string text, params object[] args) + { + return _Catalog.GetParticularString(context, text, args); + } + + public static string _pn(string context, string text, string pluralText, long n) + { + return _Catalog.GetParticularPluralString(context, text, pluralText, n); + } + + public static string _pn(string context, string text, string pluralText, long n, params object[] args) + { + return _Catalog.GetParticularPluralString(context, text, pluralText, n, args); + } + } } \ No newline at end of file diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index dbbb82a..884922c 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -1,198 +1,198 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; - -using NUnit.Framework; - -using NGettext; -using Tests.Stabs; - -namespace Tests -{ - [TestFixture] - public class BaseCatalogTest - { - [SetUp] - public void Init() - { - - } - - #region GetString - - [Test] - public void TestGetString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("key2", new[] { "value2" }); - t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - - Assert.AreEqual("value1", t.GetString("key1")); - Assert.AreEqual("value2", t.GetString("key2")); - Assert.AreEqual("value3plural1", t.GetString("key3")); - Assert.AreEqual("notFoundKey2", t.GetString("notFoundKey2")); - } - - [Test] - public void TestGetStringFormat() - { - var t = new EmptyBaseCatalog(); - - Assert.AreEqual("Foo bar", t.GetString("Foo {0}", "bar")); - Assert.AreEqual("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); - Assert.AreEqual("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); - } - - #endregion - - #region GetPluralString - - [Test] - public void TestGetPluralString() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - t.Translations.Add("key1", new[] {"value1"}); - t.Translations.Add("key2plural1", new[] {"value2plural1", "value2plural2"}); - - Assert.AreEqual("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); - Assert.AreEqual("value1", t.GetPluralString("key1", "key1", 1)); - Assert.AreEqual("key1plural", t.GetPluralString("key1", "key1plural", 2)); - - Assert.AreEqual("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); - Assert.AreEqual("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); - } - - [Test] - public void TestGetPluralStringFormat() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - - Assert.AreEqual("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.AreEqual("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.AreEqual("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); - - Assert.AreEqual("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); - Assert.AreEqual("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); - Assert.AreEqual("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); - } - - [Test] - public void TestGetPluralStringInternational() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("ru-RU")); - t.Translations.Add("You have {0} apple", new[] { "У Вас {0} яблоко", "У Вас {0} яблока", "У Вас {0} яблок" }); - - Assert.AreEqual("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.AreEqual("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.AreEqual("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); - Assert.AreEqual("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); - Assert.AreEqual("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); - Assert.AreEqual("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); - Assert.AreEqual("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); - Assert.AreEqual("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); - - Assert.AreEqual("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); - } - - #endregion - - #region GetParticularString - - [Test] - public void TestGetParticularString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value3" }); - - Assert.AreEqual("value1", t.GetString("key1")); - Assert.AreEqual("value2", t.GetParticularString("context1", "key1")); - Assert.AreEqual("value3", t.GetParticularString("context2", "key1")); - Assert.AreEqual("key1", t.GetParticularString("context3", "key1")); - } - - [Test] - public void TestGetParticularStringFormat() - { - var t = new EmptyBaseCatalog(); - - Assert.AreEqual("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); - Assert.AreEqual("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); - } - - #endregion - - #region GetParticularPluralString - - [Test] - public void TestGetParticularPluralString() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); - - Assert.AreEqual("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); - Assert.AreEqual("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); - Assert.AreEqual("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); - Assert.AreEqual("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); - } - - [Test] - public void TestGetParticularPluralStringFormat() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - - Assert.AreEqual("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); - Assert.AreEqual("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); - Assert.AreEqual("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); - Assert.AreEqual("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); - } - - #endregion - - #region *Default methods - - [Test] - public void TestProtectedGetString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - - Assert.AreEqual("value1", t.GetStringDefault("key1", null)); - Assert.AreEqual(null, t.GetStringDefault("key2", null)); - Assert.AreEqual("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); - } - - [Test] - public void TestProtectedGetPluralString() - { - var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - t.Translations.Add("key1", new[] { "value1" }); - - Assert.AreEqual("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); - Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); - Assert.AreEqual("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); - Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); - } - - [Test] - public void TestProtectedGetTranslations() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("key2", new[] { "value2" }); - t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - - Assert.AreEqual(new[] { "value1" }, t.GetTranslations("key1")); - Assert.AreEqual(new[] { "value2" }, t.GetTranslations("key2")); - Assert.AreEqual(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); - Assert.AreEqual(null, t.GetTranslations("key4")); - } - - #endregion - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Globalization; + +using NUnit.Framework; + +using NGettext; +using Tests.Stabs; + +namespace Tests +{ + [TestFixture] + public class BaseCatalogTest + { + [SetUp] + public void Init() + { + + } + + #region GetString + + [Test] + public void TestGetString() + { + var t = new EmptyBaseCatalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("key2", new[] { "value2" }); + t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); + + Assert.AreEqual("value1", t.GetString("key1")); + Assert.AreEqual("value2", t.GetString("key2")); + Assert.AreEqual("value3plural1", t.GetString("key3")); + Assert.AreEqual("notFoundKey2", t.GetString("notFoundKey2")); + } + + [Test] + public void TestGetStringFormat() + { + var t = new EmptyBaseCatalog(); + + Assert.AreEqual("Foo bar", t.GetString("Foo {0}", "bar")); + Assert.AreEqual("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); + Assert.AreEqual("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); + } + + #endregion + + #region GetPluralString + + [Test] + public void TestGetPluralString() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); + t.Translations.Add("key1", new[] {"value1"}); + t.Translations.Add("key2plural1", new[] {"value2plural1", "value2plural2"}); + + Assert.AreEqual("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); + Assert.AreEqual("value1", t.GetPluralString("key1", "key1", 1)); + Assert.AreEqual("key1plural", t.GetPluralString("key1", "key1plural", 2)); + + Assert.AreEqual("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); + Assert.AreEqual("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); + } + + [Test] + public void TestGetPluralStringFormat() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); + + Assert.AreEqual("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.AreEqual("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.AreEqual("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); + + Assert.AreEqual("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); + Assert.AreEqual("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); + Assert.AreEqual("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); + } + + [Test] + public void TestGetPluralStringInternational() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("ru-RU")); + t.Translations.Add("You have {0} apple", new[] { "У Вас {0} яблоко", "У Вас {0} яблока", "У Вас {0} яблок" }); + + Assert.AreEqual("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.AreEqual("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.AreEqual("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); + Assert.AreEqual("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); + Assert.AreEqual("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); + Assert.AreEqual("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); + Assert.AreEqual("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); + Assert.AreEqual("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); + + Assert.AreEqual("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); + } + + #endregion + + #region GetParticularString + + [Test] + public void TestGetParticularString() + { + var t = new EmptyBaseCatalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value2" }); + t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value3" }); + + Assert.AreEqual("value1", t.GetString("key1")); + Assert.AreEqual("value2", t.GetParticularString("context1", "key1")); + Assert.AreEqual("value3", t.GetParticularString("context2", "key1")); + Assert.AreEqual("key1", t.GetParticularString("context3", "key1")); + } + + [Test] + public void TestGetParticularStringFormat() + { + var t = new EmptyBaseCatalog(); + + Assert.AreEqual("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); + Assert.AreEqual("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); + } + + #endregion + + #region GetParticularPluralString + + [Test] + public void TestGetParticularPluralString() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); + t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); + t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); + + Assert.AreEqual("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); + Assert.AreEqual("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); + Assert.AreEqual("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); + Assert.AreEqual("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); + } + + [Test] + public void TestGetParticularPluralStringFormat() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); + + Assert.AreEqual("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); + Assert.AreEqual("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); + Assert.AreEqual("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); + Assert.AreEqual("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); + } + + #endregion + + #region *Default methods + + [Test] + public void TestProtectedGetString() + { + var t = new EmptyBaseCatalog(); + t.Translations.Add("key1", new[] { "value1" }); + + Assert.AreEqual("value1", t.GetStringDefault("key1", null)); + Assert.AreEqual(null, t.GetStringDefault("key2", null)); + Assert.AreEqual("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); + } + + [Test] + public void TestProtectedGetPluralString() + { + var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); + t.Translations.Add("key1", new[] { "value1" }); + + Assert.AreEqual("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); + Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); + Assert.AreEqual("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); + Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); + } + + [Test] + public void TestProtectedGetTranslations() + { + var t = new EmptyBaseCatalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("key2", new[] { "value2" }); + t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); + + Assert.AreEqual(new[] { "value1" }, t.GetTranslations("key1")); + Assert.AreEqual(new[] { "value2" }, t.GetTranslations("key2")); + Assert.AreEqual(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); + Assert.AreEqual(null, t.GetTranslations("key4")); + } + + #endregion + } } \ No newline at end of file diff --git a/src/NGettext.Tests/CatalogTest.cs b/src/NGettext.Tests/CatalogTest.cs index f47a643..15c64a6 100644 --- a/src/NGettext.Tests/CatalogTest.cs +++ b/src/NGettext.Tests/CatalogTest.cs @@ -1,67 +1,67 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; -using System.IO; -using System.Reflection; - -using NUnit.Framework; - -using NGettext; - -namespace Tests -{ - [TestFixture] - public class CatalogTest - { - public string LocalesDir; - - [SetUp] - public void Init() - { - this.LocalesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); - } - - [Test] - public void TestEmpty() - { - var t = new Catalog(); - - Assert.AreEqual(0, t.Translations.Count); - Assert.AreEqual(CultureInfo.CurrentUICulture, t.CultureInfo); - - t = new Catalog(CultureInfo.CreateSpecificCulture("fr")); - Assert.AreEqual(CultureInfo.CreateSpecificCulture("fr"), t.CultureInfo); - } - - [Test] - public void TestStream() - { - using (var stream = File.OpenRead(Path.Combine(this.LocalesDir, "ru_RU", "LC_MESSAGES", "Test.mo"))) - { - var t = new Catalog(stream, CultureInfo.CreateSpecificCulture("ru-RU")); - this._TestLoadedTranslation(t); - } - } - - [Test] - public void TestLocaleDir() - { - var t = new Catalog("Test", this.LocalesDir, CultureInfo.CreateSpecificCulture("ru-RU")); - this._TestLoadedTranslation(t); - } - - private void _TestLoadedTranslation(ICatalog t) - { - Assert.AreEqual("тест", t.GetString("test")); - Assert.AreEqual("тест2", t.GetString("test2")); - Assert.AreEqual("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); - Assert.AreEqual("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); - - Assert.AreEqual("тест3контекст1", t.GetParticularString("context1", "test3")); - Assert.AreEqual("тест3контекст2", t.GetParticularString("context2", "test3")); - } - - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Globalization; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +using NGettext; + +namespace Tests +{ + [TestFixture] + public class CatalogTest + { + public string LocalesDir; + + [SetUp] + public void Init() + { + this.LocalesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); + } + + [Test] + public void TestEmpty() + { + var t = new Catalog(); + + Assert.AreEqual(0, t.Translations.Count); + Assert.AreEqual(CultureInfo.CurrentUICulture, t.CultureInfo); + + t = new Catalog(CultureInfo.CreateSpecificCulture("fr")); + Assert.AreEqual(CultureInfo.CreateSpecificCulture("fr"), t.CultureInfo); + } + + [Test] + public void TestStream() + { + using (var stream = File.OpenRead(Path.Combine(this.LocalesDir, "ru_RU", "LC_MESSAGES", "Test.mo"))) + { + var t = new Catalog(stream, CultureInfo.CreateSpecificCulture("ru-RU")); + this._TestLoadedTranslation(t); + } + } + + [Test] + public void TestLocaleDir() + { + var t = new Catalog("Test", this.LocalesDir, CultureInfo.CreateSpecificCulture("ru-RU")); + this._TestLoadedTranslation(t); + } + + private void _TestLoadedTranslation(ICatalog t) + { + Assert.AreEqual("тест", t.GetString("test")); + Assert.AreEqual("тест2", t.GetString("test2")); + Assert.AreEqual("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); + Assert.AreEqual("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); + + Assert.AreEqual("тест3контекст1", t.GetParticularString("context1", "test3")); + Assert.AreEqual("тест3контекст2", t.GetParticularString("context2", "test3")); + } + + } } \ No newline at end of file diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 117d5a2..0335490 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Reflection; - -using NUnit.Framework; - -using NGettext; -using NGettext.Loaders; - -namespace Tests.Loaders -{ - [TestFixture] - public class MoFileParserTest - { - [Test] - public void TestParsing() - { - var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); - using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test.mo"))) - { - var parser = new MoFileParser(); - var dict = parser.GetTranslations(stream); - - Assert.AreEqual(new[] { "тест" }, dict["test"]); - Assert.AreEqual(new[] { "тест2" }, dict["test2"]); - Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); - } - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Reflection; + +using NUnit.Framework; + +using NGettext; +using NGettext.Loaders; + +namespace Tests.Loaders +{ + [TestFixture] + public class MoFileParserTest + { + [Test] + public void TestParsing() + { + var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); + using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test.mo"))) + { + var parser = new MoFileParser(); + var dict = parser.GetTranslations(stream); + + Assert.AreEqual(new[] { "тест" }, dict["test"]); + Assert.AreEqual(new[] { "тест2" }, dict["test2"]); + Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); + Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + } + } + } } \ No newline at end of file diff --git a/src/NGettext.Tests/NGettext.Tests.csproj b/src/NGettext.Tests/NGettext.Tests.csproj index 289a824..b726e9e 100644 --- a/src/NGettext.Tests/NGettext.Tests.csproj +++ b/src/NGettext.Tests/NGettext.Tests.csproj @@ -1,87 +1,87 @@ - - - - - Debug - AnyCPU - {B150FBC7-210F-4E79-B18D-3E45532067AC} - Library - Properties - NGettext.Tests - NGettext.Tests - v4.0 - 512 - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - none - true - bin\Release\ - - - prompt - 4 - - - - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll - True - - - - - - - - - - - - - - - - - - - - {96eed5f5-7e90-4bd8-a822-2d7bff943e28} - NGettext - - - - - - - PreserveNewest - - - PreserveNewest - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + Debug + AnyCPU + {B150FBC7-210F-4E79-B18D-3E45532067AC} + Library + Properties + NGettext.Tests + NGettext.Tests + v4.0 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + bin\Release\ + + + prompt + 4 + + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + True + + + + + + + + + + + + + + + + + + + + {96eed5f5-7e90-4bd8-a822-2d7bff943e28} + NGettext + + + + + + + PreserveNewest + + + PreserveNewest + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs b/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs index e020d15..92b0a34 100644 --- a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs +++ b/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs @@ -1,148 +1,148 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; - -using NUnit.Framework; - -using NGettext.Plural; - -namespace Tests.Plural -{ - [TestFixture] - public class PluralFormProcessorTest - { - - [SetUp] - public void Init() - { - - } - - #region Default forms - - [Test] - public void TestDefaultForms() - { - var dict = new Dictionary>() - { - {"en-US", new Dictionary() - { - {0, 1}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"fa-IR", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 0}, - {3, 0}, - {5, 0}, - {10, 0}, - {999, 0}, - }}, - {"ar-SA", new Dictionary() - { - {0, 0}, - {1, 1}, - {2, 2}, - {3, 3}, - {5, 3}, - {10, 3}, - {999, 5}, - }}, - {"hi", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"fr", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"lv", new Dictionary() - { - {0, 0}, - {1, 1}, - {2, 2}, - {3, 2}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - {"se-SE", new Dictionary() - { - {0, 2}, - {1, 0}, - {2, 1}, - {3, 2}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - {"ru-RU", new Dictionary() - { - {0, 2}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - }; - - - foreach (var testCase in dict) - { - var locale = CultureInfo.CreateSpecificCulture(testCase.Key); - foreach (var data in testCase.Value) - { - Assert.AreEqual(data.Value, PluralFormProcessor.Default.GetPluralFormIndex(locale, data.Key)); - } - } - } - - #endregion - - #region Custom forms - - [Test] - public void TestCustomForms() - { - var p = new PluralFormProcessor(); - - var en = CultureInfo.CreateSpecificCulture("en-US"); - p.SetCustomFormula(en, l => (int)l); - - var fr = CultureInfo.CreateSpecificCulture("fr"); - p.SetCustomFormula(fr, l => (int)(l * 2)); - - foreach (var n in new long[] { 0, 1, 2, 3, 100, 101, 102, 103 }) - { - Assert.AreEqual(n, p.GetPluralFormIndex(en, n)); - Assert.AreEqual(n * 2, p.GetPluralFormIndex(fr, n)); - } - } - - #endregion - - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Globalization; + +using NUnit.Framework; + +using NGettext.Plural; + +namespace Tests.Plural +{ + [TestFixture] + public class PluralFormProcessorTest + { + + [SetUp] + public void Init() + { + + } + + #region Default forms + + [Test] + public void TestDefaultForms() + { + var dict = new Dictionary>() + { + {"en-US", new Dictionary() + { + {0, 1}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"fa-IR", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 0}, + {3, 0}, + {5, 0}, + {10, 0}, + {999, 0}, + }}, + {"ar-SA", new Dictionary() + { + {0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {5, 3}, + {10, 3}, + {999, 5}, + }}, + {"hi", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"fr", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"lv", new Dictionary() + { + {0, 0}, + {1, 1}, + {2, 2}, + {3, 2}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + {"se-SE", new Dictionary() + { + {0, 2}, + {1, 0}, + {2, 1}, + {3, 2}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + {"ru-RU", new Dictionary() + { + {0, 2}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + }; + + + foreach (var testCase in dict) + { + var locale = CultureInfo.CreateSpecificCulture(testCase.Key); + foreach (var data in testCase.Value) + { + Assert.AreEqual(data.Value, PluralFormProcessor.Default.GetPluralFormIndex(locale, data.Key)); + } + } + } + + #endregion + + #region Custom forms + + [Test] + public void TestCustomForms() + { + var p = new PluralFormProcessor(); + + var en = CultureInfo.CreateSpecificCulture("en-US"); + p.SetCustomFormula(en, l => (int)l); + + var fr = CultureInfo.CreateSpecificCulture("fr"); + p.SetCustomFormula(fr, l => (int)(l * 2)); + + foreach (var n in new long[] { 0, 1, 2, 3, 100, 101, 102, 103 }) + { + Assert.AreEqual(n, p.GetPluralFormIndex(en, n)); + Assert.AreEqual(n * 2, p.GetPluralFormIndex(fr, n)); + } + } + + #endregion + + } } \ No newline at end of file diff --git a/src/NGettext.Tests/Properties/AssemblyInfo.cs b/src/NGettext.Tests/Properties/AssemblyInfo.cs index 207d609..5693d97 100644 --- a/src/NGettext.Tests/Properties/AssemblyInfo.cs +++ b/src/NGettext.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Tests")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("963df97c-de1a-4860-aae0-8657970d165c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tests")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("963df97c-de1a-4860-aae0-8657970d165c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs index 4a00cda..79765e5 100644 --- a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs +++ b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; - -using NGettext; - -namespace Tests.Stabs -{ - public class EmptyBaseCatalog : BaseCatalog - { - public EmptyBaseCatalog() : base(CultureInfo.CurrentUICulture) { } - - public EmptyBaseCatalog(CultureInfo cultureInfo) : base(cultureInfo) { } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Globalization; + +using NGettext; + +namespace Tests.Stabs +{ + public class EmptyBaseCatalog : BaseCatalog + { + public EmptyBaseCatalog() : base(CultureInfo.CurrentUICulture) { } + + public EmptyBaseCatalog(CultureInfo cultureInfo) : base(cultureInfo) { } + } } \ No newline at end of file diff --git a/src/NGettext.sln b/src/NGettext.sln index 5d51d0a..28bda55 100644 --- a/src/NGettext.sln +++ b/src/NGettext.sln @@ -1,28 +1,28 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext", "NGettext\NGettext.csproj", "{96EED5F5-7E90-4BD8-A822-2D7BFF943E28}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext.Tests", "NGettext.Tests\NGettext.Tests.csproj", "{B150FBC7-210F-4E79-B18D-3E45532067AC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.Build.0 = Release|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext", "NGettext\NGettext.csproj", "{96EED5F5-7E90-4BD8-A822-2D7BFF943E28}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext.Tests", "NGettext.Tests\NGettext.Tests.csproj", "{B150FBC7-210F-4E79-B18D-3E45532067AC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.Build.0 = Release|Any CPU + {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/NGettext.sln.DotSettings b/src/NGettext.sln.DotSettings index c41fe1e..123ee36 100644 --- a/src/NGettext.sln.DotSettings +++ b/src/NGettext.sln.DotSettings @@ -1,14 +1,14 @@ - - DO_NOT_SHOW - 15 - System - On$object$$event$ - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Private fields, methods, properties..."><ElementKinds><Kind Name="FIELD" /><Kind Name="METHOD" /><Kind Name="PROPERTY" /><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /></Policy> - False + + DO_NOT_SHOW + 15 + System + On$object$$event$ + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Private fields, methods, properties..."><ElementKinds><Kind Name="FIELD" /><Kind Name="METHOD" /><Kind Name="PROPERTY" /><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /></Policy> + False \ No newline at end of file diff --git a/src/NGettext/BaseCatalog.cs b/src/NGettext/BaseCatalog.cs index e634e3e..3d24160 100644 --- a/src/NGettext/BaseCatalog.cs +++ b/src/NGettext/BaseCatalog.cs @@ -1,211 +1,211 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; - -using NGettext.Plural; - -namespace NGettext -{ - /// - /// Base catalog. - /// - public abstract class BaseCatalog : ICatalog - { - /// - /// Context glue (<EOT> symbol) - /// - public const char CONTEXT_GLUE = '\u0004'; - - /// - /// Current catalog locale. - /// - public CultureInfo CultureInfo { get; protected set; } - - /// - /// Current plural form processor. - /// - public PluralFormProcessor PluralForms { get; protected set; } - - /// - /// Loaded raw translation strings. - /// (msgctxt<EOT>)msgid => msgstr[] - /// - public Dictionary Translations { get; protected set; } - - /// - /// Initializes a new instance of the class that has no translations, - /// with default plural form formulas, using given culture info. - /// - /// Locale of this catalog. - protected BaseCatalog(CultureInfo cultureInfo) - { - this.CultureInfo = cultureInfo; - this.PluralForms = PluralFormProcessor.Default; - this.Translations = new Dictionary(); - } - - #region ICatalog implementation - - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Translated text. - public virtual string GetString(string text) - { - return this.GetStringDefault(text, text); - } - - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - public virtual string GetString(string text, params object[] args) - { - return String.Format(this.GetStringDefault(text, text), args); - } - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - public virtual string GetPluralString(string text, string pluralText, long n) - { - return this.GetPluralStringDefault(text, text, pluralText, n); - } - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - public virtual string GetPluralString(string text, string pluralText, long n, params object[] args) - { - return String.Format(this.GetPluralStringDefault(text, text, pluralText, n), args); - } - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Translated text. - public virtual string GetParticularString(string context, string text) - { - return this.GetStringDefault(context + CONTEXT_GLUE + text, text); - } - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - public virtual string GetParticularString(string context, string text, params object[] args) - { - return String.Format(this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); - } - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - public virtual string GetParticularPluralString(string context, string text, string pluralText, long n) - { - return this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n); - } - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - public virtual string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args) - { - return String.Format(this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); - } - - #endregion - - /// - /// Returns translated string for given or on fail. - /// - /// Message ID - /// Default message - /// Translated string - public virtual string GetStringDefault(string messageId, string defaultMessage) - { - var translations = this.GetTranslations(messageId); - - if (translations == null || translations.Length == 0) - { - Trace.WriteLine(String.Format("Translation not found for message id \"{0}\".", messageId), "NGettext"); - return defaultMessage; - } - - return translations[0]; - } - - /// - /// Returns translated plural string for given or - /// or on fail. - /// - /// Message ID - /// Default message singular form - /// Default message plural form - /// Value that determines the plural form - /// Translated string - public virtual string GetPluralStringDefault(string messageId, string defaultMessage, string defaultPluralMessage, long n) - { - var translations = this.GetTranslations(messageId); - var pluralIndex = this.PluralForms.GetPluralFormIndex(this.CultureInfo, n); - - if (translations == null || translations.Length <= pluralIndex) - { - Trace.WriteLine(String.Format("Translation not found (plural) for message id \"{0}\".", messageId), "NGettext"); - return (n == 1) ? defaultMessage : defaultPluralMessage; - } - - return translations[pluralIndex]; - } - - /// - /// Returns all translations for given . - /// - /// - /// Returns all translations for given or null if not found. - public virtual string[] GetTranslations(string messageId) - { - if (String.IsNullOrEmpty(messageId)) return null; - if (!this.Translations.ContainsKey(messageId)) return null; - - return this.Translations[messageId]; - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +using NGettext.Plural; + +namespace NGettext +{ + /// + /// Base catalog. + /// + public abstract class BaseCatalog : ICatalog + { + /// + /// Context glue (<EOT> symbol) + /// + public const char CONTEXT_GLUE = '\u0004'; + + /// + /// Current catalog locale. + /// + public CultureInfo CultureInfo { get; protected set; } + + /// + /// Current plural form processor. + /// + public PluralFormProcessor PluralForms { get; protected set; } + + /// + /// Loaded raw translation strings. + /// (msgctxt<EOT>)msgid => msgstr[] + /// + public Dictionary Translations { get; protected set; } + + /// + /// Initializes a new instance of the class that has no translations, + /// with default plural form formulas, using given culture info. + /// + /// Locale of this catalog. + protected BaseCatalog(CultureInfo cultureInfo) + { + this.CultureInfo = cultureInfo; + this.PluralForms = PluralFormProcessor.Default; + this.Translations = new Dictionary(); + } + + #region ICatalog implementation + + /// + /// Returns translated into the selected language. + /// Similar to gettext function. + /// + /// Text to translate. + /// Translated text. + public virtual string GetString(string text) + { + return this.GetStringDefault(text, text); + } + + /// + /// Returns translated into the selected language. + /// Similar to gettext function. + /// + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + public virtual string GetString(string text, params object[] args) + { + return String.Format(this.GetStringDefault(text, text), args); + } + + /// + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. + /// + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + public virtual string GetPluralString(string text, string pluralText, long n) + { + return this.GetPluralStringDefault(text, text, pluralText, n); + } + + /// + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. + /// + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + public virtual string GetPluralString(string text, string pluralText, long n, params object[] args) + { + return String.Format(this.GetPluralStringDefault(text, text, pluralText, n), args); + } + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Translated text. + public virtual string GetParticularString(string context, string text) + { + return this.GetStringDefault(context + CONTEXT_GLUE + text, text); + } + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + public virtual string GetParticularString(string context, string text, params object[] args) + { + return String.Format(this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); + } + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + public virtual string GetParticularPluralString(string context, string text, string pluralText, long n) + { + return this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n); + } + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + public virtual string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args) + { + return String.Format(this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); + } + + #endregion + + /// + /// Returns translated string for given or on fail. + /// + /// Message ID + /// Default message + /// Translated string + public virtual string GetStringDefault(string messageId, string defaultMessage) + { + var translations = this.GetTranslations(messageId); + + if (translations == null || translations.Length == 0) + { + Trace.WriteLine(String.Format("Translation not found for message id \"{0}\".", messageId), "NGettext"); + return defaultMessage; + } + + return translations[0]; + } + + /// + /// Returns translated plural string for given or + /// or on fail. + /// + /// Message ID + /// Default message singular form + /// Default message plural form + /// Value that determines the plural form + /// Translated string + public virtual string GetPluralStringDefault(string messageId, string defaultMessage, string defaultPluralMessage, long n) + { + var translations = this.GetTranslations(messageId); + var pluralIndex = this.PluralForms.GetPluralFormIndex(this.CultureInfo, n); + + if (translations == null || translations.Length <= pluralIndex) + { + Trace.WriteLine(String.Format("Translation not found (plural) for message id \"{0}\".", messageId), "NGettext"); + return (n == 1) ? defaultMessage : defaultPluralMessage; + } + + return translations[pluralIndex]; + } + + /// + /// Returns all translations for given . + /// + /// + /// Returns all translations for given or null if not found. + public virtual string[] GetTranslations(string messageId) + { + if (String.IsNullOrEmpty(messageId)) return null; + if (!this.Translations.ContainsKey(messageId)) return null; + + return this.Translations[messageId]; + } + } } \ No newline at end of file diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index eafa22f..1dbf501 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -1,188 +1,188 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Globalization; -using System.Text; - -using NGettext.Loaders; - -namespace NGettext -{ - /// - /// Represents a Gettext catalog instance. - /// Loads translations from gettext *.mo files. - /// - public class Catalog : BaseCatalog - { - /// - /// Initializes a new instance of the class with no translations and with current CultureInfo. - /// - public Catalog() - : base(CultureInfo.CurrentUICulture) - { - - } - - /// - /// Initializes a new instance of the class with no translations and with given CultureInfo. - /// - /// Culture info - public Catalog(CultureInfo cultureInfo) - : base(cultureInfo) - { - - } - - /// - /// Initializes a new instance of the class with current CultureInfo - /// and loads MO translations from given stream. - /// - /// Stream that contain binary data in the MO file format - public Catalog(Stream moStream) - : this() - { - try - { - this.Load(moStream); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } - } - - /// - /// Initializes a new instance of the class with given CultureInfo - /// and loads MO translations from given stream. - /// - /// Stream that contain binary data in the MO file format - /// Culture info - public Catalog(Stream moStream, CultureInfo cultureInfo) - : this(cultureInfo) - { - try - { - this.Load(moStream); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } - } - - /// - /// Initializes a new instance of the class with current CultureInfo - /// and loads translations from MO file that can be found by given parameters. - /// - /// Catalog domain name - /// Directory that contains gettext localization files - public Catalog(string domain, string localeDir) - : this() - { - try - { - this.Load(this.CultureInfo, domain, localeDir); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } - } - - /// - /// Initializes a new instance of the class with given CultureInfo - /// and loads translations from MO file that can be found by given parameters. - /// - /// Catalog domain name - /// Directory that contains gettext localization files - /// Culture info - public Catalog(string domain, string localeDir, CultureInfo cultureInfo) - : this(cultureInfo) - { - try - { - this.Load(this.CultureInfo, domain, localeDir); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } - } - - /// - /// Load translations from MO file that can be found by given parameters. - /// - /// Culture info - /// Catalog domain name - /// Directory that contains gettext localization files - public void Load(CultureInfo cultureInfo, string domain, string localeDir) - { - var path = this._FindTranslationFile(cultureInfo, domain, localeDir); - if (path == null) - { - throw new FileNotFoundException(String.Format("Can not find MO file name in locale directory \"{0}\".", localeDir)); - } - - this.Load(path); - } - - /// - /// Load translations from MO file that can be found by given path. - /// - /// Path to *.mo file - public void Load(string path) - { - Trace.WriteLine(String.Format("Loading translations from file \"{0}\"...", path), "NGettext"); - using (var stream = File.OpenRead(path)) - { - this.Load(stream); - } - } - - /// - /// Load translations from given MO file stream using given encoding (UTF-8 encoding by default). - /// - /// Stream that contain binary data in the MO file format - /// File encoding (UTF-8 by default) - public void Load(Stream moStream, Encoding encoding = null) - { - var parser = new MoFileParser(); - if (encoding != null) - { - parser.Encoding = encoding; - } - - var translations = parser.GetTranslations(moStream); - - this.Translations = translations; - } - - private string _FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) - { - var possibleFiles = new [] { - this._GetFileName(localeDir, domain, cultureInfo.Name), - this._GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) - }; - - foreach (var possibleFilePath in possibleFiles) - { - if (File.Exists(possibleFilePath)) - { - return possibleFilePath; - } - } - - return null; - } - - private string _GetFileName(string localeDir, string domain, string locale) - { - var relativePath = - locale.Replace('-', '_') + Path.DirectorySeparatorChar + - "LC_MESSAGES" + Path.DirectorySeparatorChar + - domain + ".mo"; - - return Path.Combine(localeDir, relativePath); - } - } +using System; +using System.Diagnostics; +using System.IO; +using System.Globalization; +using System.Text; + +using NGettext.Loaders; + +namespace NGettext +{ + /// + /// Represents a Gettext catalog instance. + /// Loads translations from gettext *.mo files. + /// + public class Catalog : BaseCatalog + { + /// + /// Initializes a new instance of the class with no translations and with current CultureInfo. + /// + public Catalog() + : base(CultureInfo.CurrentUICulture) + { + + } + + /// + /// Initializes a new instance of the class with no translations and with given CultureInfo. + /// + /// Culture info + public Catalog(CultureInfo cultureInfo) + : base(cultureInfo) + { + + } + + /// + /// Initializes a new instance of the class with current CultureInfo + /// and loads MO translations from given stream. + /// + /// Stream that contain binary data in the MO file format + public Catalog(Stream moStream) + : this() + { + try + { + this.Load(moStream); + } + catch (FileNotFoundException exception) + { + Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); + } + } + + /// + /// Initializes a new instance of the class with given CultureInfo + /// and loads MO translations from given stream. + /// + /// Stream that contain binary data in the MO file format + /// Culture info + public Catalog(Stream moStream, CultureInfo cultureInfo) + : this(cultureInfo) + { + try + { + this.Load(moStream); + } + catch (FileNotFoundException exception) + { + Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); + } + } + + /// + /// Initializes a new instance of the class with current CultureInfo + /// and loads translations from MO file that can be found by given parameters. + /// + /// Catalog domain name + /// Directory that contains gettext localization files + public Catalog(string domain, string localeDir) + : this() + { + try + { + this.Load(this.CultureInfo, domain, localeDir); + } + catch (FileNotFoundException exception) + { + Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); + } + } + + /// + /// Initializes a new instance of the class with given CultureInfo + /// and loads translations from MO file that can be found by given parameters. + /// + /// Catalog domain name + /// Directory that contains gettext localization files + /// Culture info + public Catalog(string domain, string localeDir, CultureInfo cultureInfo) + : this(cultureInfo) + { + try + { + this.Load(this.CultureInfo, domain, localeDir); + } + catch (FileNotFoundException exception) + { + Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); + } + } + + /// + /// Load translations from MO file that can be found by given parameters. + /// + /// Culture info + /// Catalog domain name + /// Directory that contains gettext localization files + public void Load(CultureInfo cultureInfo, string domain, string localeDir) + { + var path = this._FindTranslationFile(cultureInfo, domain, localeDir); + if (path == null) + { + throw new FileNotFoundException(String.Format("Can not find MO file name in locale directory \"{0}\".", localeDir)); + } + + this.Load(path); + } + + /// + /// Load translations from MO file that can be found by given path. + /// + /// Path to *.mo file + public void Load(string path) + { + Trace.WriteLine(String.Format("Loading translations from file \"{0}\"...", path), "NGettext"); + using (var stream = File.OpenRead(path)) + { + this.Load(stream); + } + } + + /// + /// Load translations from given MO file stream using given encoding (UTF-8 encoding by default). + /// + /// Stream that contain binary data in the MO file format + /// File encoding (UTF-8 by default) + public void Load(Stream moStream, Encoding encoding = null) + { + var parser = new MoFileParser(); + if (encoding != null) + { + parser.Encoding = encoding; + } + + var translations = parser.GetTranslations(moStream); + + this.Translations = translations; + } + + private string _FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) + { + var possibleFiles = new [] { + this._GetFileName(localeDir, domain, cultureInfo.Name), + this._GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) + }; + + foreach (var possibleFilePath in possibleFiles) + { + if (File.Exists(possibleFilePath)) + { + return possibleFilePath; + } + } + + return null; + } + + private string _GetFileName(string localeDir, string domain, string locale) + { + var relativePath = + locale.Replace('-', '_') + Path.DirectorySeparatorChar + + "LC_MESSAGES" + Path.DirectorySeparatorChar + + domain + ".mo"; + + return Path.Combine(localeDir, relativePath); + } + } } \ No newline at end of file diff --git a/src/NGettext/ICatalog.cs b/src/NGettext/ICatalog.cs index f28caee..5da8b4c 100644 --- a/src/NGettext/ICatalog.cs +++ b/src/NGettext/ICatalog.cs @@ -1,90 +1,90 @@ -using System; - -namespace NGettext -{ - /// - /// Represents a Gettext catalog instance. - /// - public interface ICatalog - { - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Translated text. - string GetString(string text); - - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - string GetString(string text, params object[] args); - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - string GetPluralString(string text, string pluralText, long n); - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - string GetPluralString(string text, string pluralText, long n, params object[] args); - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Translated text. - string GetParticularString(string context, string text); - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - string GetParticularString(string context, string text, params object[] args); - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - string GetParticularPluralString(string context, string text, string pluralText, long n); - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args); - } +using System; + +namespace NGettext +{ + /// + /// Represents a Gettext catalog instance. + /// + public interface ICatalog + { + /// + /// Returns translated into the selected language. + /// Similar to gettext function. + /// + /// Text to translate. + /// Translated text. + string GetString(string text); + + /// + /// Returns translated into the selected language. + /// Similar to gettext function. + /// + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + string GetString(string text, params object[] args); + + /// + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. + /// + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + string GetPluralString(string text, string pluralText, long n); + + /// + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. + /// + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + string GetPluralString(string text, string pluralText, long n, params object[] args); + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Translated text. + string GetParticularString(string context, string text); + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + string GetParticularString(string context, string text, params object[] args); + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + string GetParticularPluralString(string context, string text, string pluralText, long n); + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args); + } } \ No newline at end of file diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index 66d10f6..ce80c0f 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -1,124 +1,124 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using System.IO; - -namespace NGettext.Loaders -{ - /// - /// MO file format parser. - /// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html - /// - public class MoFileParser - { +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.IO; + +namespace NGettext.Loaders +{ + /// + /// MO file format parser. + /// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html + /// + public class MoFileParser + { /// /// MO file format magic number. - /// - public const uint MO_FILE_MAGIC = 0x950412de; - - private struct StringOffsetTable - { - public int Length; - public int Offset; - } - - /// - /// Current encoding for decoding all strings in given MO file. - /// - public Encoding Encoding { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public MoFileParser() - { - this.Encoding = Encoding.UTF8; - } - - /// - /// Read and load all translation strings from given MO file stream. - /// - /// - /// http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html - /// - /// Stream that contain binary data in the MO file format - /// Raw translations - public Dictionary GetTranslations(Stream stream) - { - Trace.WriteLine("Trying to parse a MO file stream...", "NGettext"); - - if (stream == null || stream.Length < 20) - { - throw new ArgumentException("Stream can not be null of less than 20 bytes long."); - } - - var reader = new BinaryReader(stream); + /// + public const uint MO_FILE_MAGIC = 0x950412de; + + private struct StringOffsetTable + { + public int Length; + public int Offset; + } + + /// + /// Current encoding for decoding all strings in given MO file. + /// + public Encoding Encoding { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public MoFileParser() + { + this.Encoding = Encoding.UTF8; + } + + /// + /// Read and load all translation strings from given MO file stream. + /// + /// + /// http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html + /// + /// Stream that contain binary data in the MO file format + /// Raw translations + public Dictionary GetTranslations(Stream stream) + { + Trace.WriteLine("Trying to parse a MO file stream...", "NGettext"); + + if (stream == null || stream.Length < 20) + { + throw new ArgumentException("Stream can not be null of less than 20 bytes long."); + } + + var reader = new BinaryReader(stream); var magicNumber = reader.ReadUInt32(); - if (magicNumber != MO_FILE_MAGIC) - { - throw new ArgumentException("Invalid stream: can not find MO file magic number."); - } - - var revision = reader.ReadUInt32(); - Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", revision >> 16, revision & 0xffff), "NGettext"); - - if ((revision >> 16) > 1) - { - throw new Exception(String.Format("Unsupported MO file major revision: {0}.", revision >> 16)); - } - - var stringCount = reader.ReadInt32(); - var originalTableOffset = reader.ReadInt32(); - var translationTableOffset = reader.ReadInt32(); - - // We don't support hash tables and system dependent segments. - - Trace.WriteLine(String.Format("MO File contains {0} strings.", stringCount), "NGettext"); - - - - var originalTable = new StringOffsetTable[stringCount]; - var translationTable = new StringOffsetTable[stringCount]; - - Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); - - reader.BaseStream.Seek(originalTableOffset, SeekOrigin.Begin); - for (int i = 0; i < stringCount; i++) - { - originalTable[i].Length = reader.ReadInt32(); - originalTable[i].Offset = reader.ReadInt32(); - } - - reader.BaseStream.Seek(translationTableOffset, SeekOrigin.Begin); - for (int i = 0; i < stringCount; i++) - { - translationTable[i].Length = reader.ReadInt32(); - translationTable[i].Offset = reader.ReadInt32(); - } - - - var dict = new Dictionary(stringCount); - - for (int i = 0; i < stringCount; i++) - { - var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); - var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); - - dict.Add(originalStrings[0], translatedStrings); - } - - Trace.WriteLine("String parsing completed.", "NGettext"); - - return dict; - } - - private string[] _ReadStrings(BinaryReader reader, int offset, int length) - { - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - var stringBytes = reader.ReadBytes(length); - return this.Encoding.GetString(stringBytes).Split('\0'); - } - } + if (magicNumber != MO_FILE_MAGIC) + { + throw new ArgumentException("Invalid stream: can not find MO file magic number."); + } + + var revision = reader.ReadUInt32(); + Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", revision >> 16, revision & 0xffff), "NGettext"); + + if ((revision >> 16) > 1) + { + throw new Exception(String.Format("Unsupported MO file major revision: {0}.", revision >> 16)); + } + + var stringCount = reader.ReadInt32(); + var originalTableOffset = reader.ReadInt32(); + var translationTableOffset = reader.ReadInt32(); + + // We don't support hash tables and system dependent segments. + + Trace.WriteLine(String.Format("MO File contains {0} strings.", stringCount), "NGettext"); + + + + var originalTable = new StringOffsetTable[stringCount]; + var translationTable = new StringOffsetTable[stringCount]; + + Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); + + reader.BaseStream.Seek(originalTableOffset, SeekOrigin.Begin); + for (int i = 0; i < stringCount; i++) + { + originalTable[i].Length = reader.ReadInt32(); + originalTable[i].Offset = reader.ReadInt32(); + } + + reader.BaseStream.Seek(translationTableOffset, SeekOrigin.Begin); + for (int i = 0; i < stringCount; i++) + { + translationTable[i].Length = reader.ReadInt32(); + translationTable[i].Offset = reader.ReadInt32(); + } + + + var dict = new Dictionary(stringCount); + + for (int i = 0; i < stringCount; i++) + { + var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); + var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); + + dict.Add(originalStrings[0], translatedStrings); + } + + Trace.WriteLine("String parsing completed.", "NGettext"); + + return dict; + } + + private string[] _ReadStrings(BinaryReader reader, int offset, int length) + { + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + var stringBytes = reader.ReadBytes(length); + return this.Encoding.GetString(stringBytes).Split('\0'); + } + } } \ No newline at end of file diff --git a/src/NGettext/NGettext.csproj b/src/NGettext/NGettext.csproj index e4b3126..253e587 100644 --- a/src/NGettext/NGettext.csproj +++ b/src/NGettext/NGettext.csproj @@ -1,62 +1,62 @@ - - - - - Debug - AnyCPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28} - Library - Properties - NGettext - NGettext - v2.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - $(DocumentationDir)NGettext.xml - $(OutputPath)NGettext.xml - - - none - true - bin\Release\ - - - prompt - 4 - $(DocumentationDir)NGettext.xml - $(OutputPath)NGettext.xml - false - - - true - ..\..\NGettext.snk - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {96EED5F5-7E90-4BD8-A822-2D7BFF943E28} + Library + Properties + NGettext + NGettext + v2.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + $(DocumentationDir)NGettext.xml + $(OutputPath)NGettext.xml + + + none + true + bin\Release\ + + + prompt + 4 + $(DocumentationDir)NGettext.xml + $(OutputPath)NGettext.xml + false + + + true + ..\..\NGettext.snk + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/NGettext/Plural/PluralFormProcessor.cs b/src/NGettext/Plural/PluralFormProcessor.cs index 6ad0817..afb1936 100644 --- a/src/NGettext/Plural/PluralFormProcessor.cs +++ b/src/NGettext/Plural/PluralFormProcessor.cs @@ -1,285 +1,285 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; - -namespace NGettext.Plural -{ - /// - /// Plural forms processor. - /// - public class PluralFormProcessor - { - /// - /// Returns plural form index by given number. - /// - /// - /// - public delegate int FormulaDelegate(long n); - - /// - /// Default plural forms processor. - /// - public static readonly PluralFormProcessor Default = new PluralFormProcessor(); - - /// - /// Collection with custom plural forms formulas. - /// Culture Info LCID => Formula function - /// - private readonly Dictionary _CustomFormulas = new Dictionary(); - - /// - /// Set custom plural form formula function for given locale. - /// - /// Locale - /// Function that returns plural form index by given number. - public void SetCustomFormula(CultureInfo cultureInfo, FormulaDelegate formula) - { - this._CustomFormulas.Add(cultureInfo.LCID, formula); - } - - /// - /// Get plural form index for given locale by given number. - /// - /// - /// Default furmulas created using information from http://cldr.unicode.org/ - /// - /// - /// - /// - public int GetPluralFormIndex(CultureInfo cultureInfo, long number) - { - Trace.WriteLine(String.Format("Getting plural index for locale \"{0}\" and number \"{1}\".", cultureInfo.Name, number), "NGettext"); - - if (this._CustomFormulas.ContainsKey(cultureInfo.LCID)) - { - var formula = this._CustomFormulas[cultureInfo.LCID]; - if (formula != null) - { - Trace.WriteLine(String.Format("Using custom plural formula for locale \"{0}\".", cultureInfo.Name), "NGettext"); - return formula.Invoke(number); - } - } - - var langCode = cultureInfo.TwoLetterISOLanguageName; - Trace.WriteLine(String.Format("Using built-in plural formula with langcode \"{0}\" for locale \"{1}\".", langCode, cultureInfo.Name), "NGettext"); - - - switch (langCode) - { - case "az": - case "bm": - case "bo": - case "dz": - case "fa": - case "id": - case "ig": - case "ii": - case "hu": - case "ja": - case "jv": - case "ka": - case "kde": - case "kea": - case "km": - case "kn": - case "ko": - case "lo": - case "ms": - case "my": - case "sah": - case "ses": - case "sg": - case "th": - case "to": - case "tr": - case "vi": - case "wo": - case "yo": - case "zh": - return 0; - - case "ar": - return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : (((number >= 3) && (number <= 10)) ? 3 : (((number >= 11) && (number <= 99)) ? 4 : 5)))); - - case "asa": - case "af": - case "bem": - case "bez": - case "bg": - case "bn": - case "brx": - case "ca": - case "cgg": - case "chr": - case "da": - case "de": - case "dv": - case "ee": - case "el": - case "en": - case "eo": - case "es": - case "et": - case "eu": - case "fi": - case "fo": - case "fur": - case "fy": - case "gl": - case "gsw": - case "gu": - case "ha": - case "haw": - case "he": - case "is": - case "it": - case "jmc": - case "kaj": - case "kcg": - case "kk": - case "kl": - case "ksb": - case "ku": - case "lb": - case "lg": - case "mas": - case "ml": - case "mn": - case "mr": - case "nah": - case "nb": - case "nd": - case "ne": - case "nl": - case "nn": - case "no": - case "nr": - case "ny": - case "nyn": - case "om": - case "or": - case "pa": - case "pap": - case "ps": - case "pt": - case "rof": - case "rm": - case "rwk": - case "saq": - case "seh": - case "sn": - case "so": - case "sq": - case "ss": - case "ssy": - case "st": - case "sv": - case "sw": - case "syr": - case "ta": - case "te": - case "teo": - case "tig": - case "tk": - case "tn": - case "ts": - case "ur": - case "wae": - case "ve": - case "vun": - case "xh": - case "xog": - case "zu": - return (number == 1) ? 0 : 1; - - case "ak": - case "am": - case "bh": - case "fil": - case "ff": - case "fr": - case "guw": - case "hi": - case "kab": - case "ln": - case "mg": - case "nso": - case "ti": - case "wa": - return ((number == 0) || (number == 1)) ? 0 : 1; - - case "lv": - return (number == 0) ? 0 : (((number % 10 == 1) && (number % 100 != 11)) ? 1 : 2); - - case "iu": - case "kw": - case "naq": - case "se": - case "sma": - case "smi": - case "smj": - case "smn": - case "sms": - return (number == 1) ? 0 : ((number == 2) ? 1 : 2); - - case "ga": - return (number == 1) ? 0 : ((number == 2) ? 1 : (((number >= 3) && (number <= 6)) ? 2 : ((number >= 7 && number <= 10) ? 3 : 4))); - - case "ro": - case "mo": - return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2); - - case "lt": - return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); - - case "be": - case "bs": - case "hr": - case "ru": - case "sh": - case "sr": - case "uk": - return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); - - case "cs": - case "sk": - return (number == 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2); - - case "pl": - return (number == 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2); - - case "sl": - return (number % 100 == 1) ? 0 : ((number % 100 == 2) ? 1 : (((number % 100 == 3) || (number % 100 == 4)) ? 2 : 3)); - - case "mt": - return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3)); - - case "mk": - return ((number % 10 == 1) && (number != 11)) ? 0 : 1; - - case "cy": - return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : ((number == 3) ? 3 : ((number == 6) ? 4 : 5)))); - - case "lag": - case "ksh": - return (number == 0) ? 0 : ((number == 1) ? 1 : 2); - - case "shi": - return ((number == 0) && (number == 1)) ? 0 : (((number >= 2) && (number <= 10)) ? 1 : 2); - - case "tzm": - return ((number == 0) || (number == 1) || (((number >= 11) && (number <= 99)))) ? 0 : 1; - - case "gv": - return ((number % 10 == 1) || (number % 10 == 2) || (number % 20 == 0)) ? 0 : 1; - - case "gd": - return ((number == 1) || (number == 11)) ? 0 : (((number == 2) || (number == 12)) ? 1 : (((((number >= 3) && (number <= 10)) || ((number >= 13) && (number <= 19))) ? 2 : 3))); - - default: - return 0; - } - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace NGettext.Plural +{ + /// + /// Plural forms processor. + /// + public class PluralFormProcessor + { + /// + /// Returns plural form index by given number. + /// + /// + /// + public delegate int FormulaDelegate(long n); + + /// + /// Default plural forms processor. + /// + public static readonly PluralFormProcessor Default = new PluralFormProcessor(); + + /// + /// Collection with custom plural forms formulas. + /// Culture Info LCID => Formula function + /// + private readonly Dictionary _CustomFormulas = new Dictionary(); + + /// + /// Set custom plural form formula function for given locale. + /// + /// Locale + /// Function that returns plural form index by given number. + public void SetCustomFormula(CultureInfo cultureInfo, FormulaDelegate formula) + { + this._CustomFormulas.Add(cultureInfo.LCID, formula); + } + + /// + /// Get plural form index for given locale by given number. + /// + /// + /// Default furmulas created using information from http://cldr.unicode.org/ + /// + /// + /// + /// + public int GetPluralFormIndex(CultureInfo cultureInfo, long number) + { + Trace.WriteLine(String.Format("Getting plural index for locale \"{0}\" and number \"{1}\".", cultureInfo.Name, number), "NGettext"); + + if (this._CustomFormulas.ContainsKey(cultureInfo.LCID)) + { + var formula = this._CustomFormulas[cultureInfo.LCID]; + if (formula != null) + { + Trace.WriteLine(String.Format("Using custom plural formula for locale \"{0}\".", cultureInfo.Name), "NGettext"); + return formula.Invoke(number); + } + } + + var langCode = cultureInfo.TwoLetterISOLanguageName; + Trace.WriteLine(String.Format("Using built-in plural formula with langcode \"{0}\" for locale \"{1}\".", langCode, cultureInfo.Name), "NGettext"); + + + switch (langCode) + { + case "az": + case "bm": + case "bo": + case "dz": + case "fa": + case "id": + case "ig": + case "ii": + case "hu": + case "ja": + case "jv": + case "ka": + case "kde": + case "kea": + case "km": + case "kn": + case "ko": + case "lo": + case "ms": + case "my": + case "sah": + case "ses": + case "sg": + case "th": + case "to": + case "tr": + case "vi": + case "wo": + case "yo": + case "zh": + return 0; + + case "ar": + return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : (((number >= 3) && (number <= 10)) ? 3 : (((number >= 11) && (number <= 99)) ? 4 : 5)))); + + case "asa": + case "af": + case "bem": + case "bez": + case "bg": + case "bn": + case "brx": + case "ca": + case "cgg": + case "chr": + case "da": + case "de": + case "dv": + case "ee": + case "el": + case "en": + case "eo": + case "es": + case "et": + case "eu": + case "fi": + case "fo": + case "fur": + case "fy": + case "gl": + case "gsw": + case "gu": + case "ha": + case "haw": + case "he": + case "is": + case "it": + case "jmc": + case "kaj": + case "kcg": + case "kk": + case "kl": + case "ksb": + case "ku": + case "lb": + case "lg": + case "mas": + case "ml": + case "mn": + case "mr": + case "nah": + case "nb": + case "nd": + case "ne": + case "nl": + case "nn": + case "no": + case "nr": + case "ny": + case "nyn": + case "om": + case "or": + case "pa": + case "pap": + case "ps": + case "pt": + case "rof": + case "rm": + case "rwk": + case "saq": + case "seh": + case "sn": + case "so": + case "sq": + case "ss": + case "ssy": + case "st": + case "sv": + case "sw": + case "syr": + case "ta": + case "te": + case "teo": + case "tig": + case "tk": + case "tn": + case "ts": + case "ur": + case "wae": + case "ve": + case "vun": + case "xh": + case "xog": + case "zu": + return (number == 1) ? 0 : 1; + + case "ak": + case "am": + case "bh": + case "fil": + case "ff": + case "fr": + case "guw": + case "hi": + case "kab": + case "ln": + case "mg": + case "nso": + case "ti": + case "wa": + return ((number == 0) || (number == 1)) ? 0 : 1; + + case "lv": + return (number == 0) ? 0 : (((number % 10 == 1) && (number % 100 != 11)) ? 1 : 2); + + case "iu": + case "kw": + case "naq": + case "se": + case "sma": + case "smi": + case "smj": + case "smn": + case "sms": + return (number == 1) ? 0 : ((number == 2) ? 1 : 2); + + case "ga": + return (number == 1) ? 0 : ((number == 2) ? 1 : (((number >= 3) && (number <= 6)) ? 2 : ((number >= 7 && number <= 10) ? 3 : 4))); + + case "ro": + case "mo": + return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2); + + case "lt": + return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); + + case "be": + case "bs": + case "hr": + case "ru": + case "sh": + case "sr": + case "uk": + return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); + + case "cs": + case "sk": + return (number == 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2); + + case "pl": + return (number == 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2); + + case "sl": + return (number % 100 == 1) ? 0 : ((number % 100 == 2) ? 1 : (((number % 100 == 3) || (number % 100 == 4)) ? 2 : 3)); + + case "mt": + return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3)); + + case "mk": + return ((number % 10 == 1) && (number != 11)) ? 0 : 1; + + case "cy": + return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : ((number == 3) ? 3 : ((number == 6) ? 4 : 5)))); + + case "lag": + case "ksh": + return (number == 0) ? 0 : ((number == 1) ? 1 : 2); + + case "shi": + return ((number == 0) && (number == 1)) ? 0 : (((number >= 2) && (number <= 10)) ? 1 : 2); + + case "tzm": + return ((number == 0) || (number == 1) || (((number >= 11) && (number <= 99)))) ? 0 : 1; + + case "gv": + return ((number % 10 == 1) || (number % 10 == 2) || (number % 20 == 0)) ? 0 : 1; + + case "gd": + return ((number == 1) || (number == 11)) ? 0 : (((number == 2) || (number == 12)) ? 1 : (((((number >= 3) && (number <= 10)) || ((number >= 13) && (number <= 19))) ? 2 : 3))); + + default: + return 0; + } + } + } } \ No newline at end of file diff --git a/src/NGettext/Properties/AssemblyInfo.cs b/src/NGettext/Properties/AssemblyInfo.cs index 3071871..8ea174c 100644 --- a/src/NGettext/Properties/AssemblyInfo.cs +++ b/src/NGettext/Properties/AssemblyInfo.cs @@ -1,24 +1,24 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - - -[assembly: AssemblyTitle("NGettext")] -[assembly: AssemblyDescription(".NET implementation of GNU/Gettext library")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NGettext")] -[assembly: AssemblyCopyright("Copyright © 2012 Neris Ereptoris (www.neris.ws)")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: AssemblyVersion("0.2.2.1")] -[assembly: AssemblyFileVersion("0.2.2.1")] - -[assembly: Guid("9ef9b9d7-7df8-4c3a-ac8c-58bea65f0526")] - -[assembly: ComVisible(true)] -[assembly: CLSCompliant(true)] - - +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + + +[assembly: AssemblyTitle("NGettext")] +[assembly: AssemblyDescription(".NET implementation of GNU/Gettext library")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NGettext")] +[assembly: AssemblyCopyright("Copyright © 2012 Neris Ereptoris (www.neris.ws)")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: AssemblyVersion("0.2.2.1")] +[assembly: AssemblyFileVersion("0.2.2.1")] + +[assembly: Guid("9ef9b9d7-7df8-4c3a-ac8c-58bea65f0526")] + +[assembly: ComVisible(true)] +[assembly: CLSCompliant(true)] + + From e1d72f0b4638f9da01980fbe40863ddaf3081c1c Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 May 2015 17:07:52 +0300 Subject: [PATCH 04/55] Initial big-endian mo file support. --- src/NGettext/Loaders/BigEndianBinaryReader.cs | 217 ++++++++++++++++++ src/NGettext/Loaders/MoFileParser.cs | 108 +++++---- src/NGettext/Loaders/ReadOnlyStreamWrapper.cs | 131 +++++++++++ src/NGettext/NGettext.csproj | 2 + 4 files changed, 415 insertions(+), 43 deletions(-) create mode 100644 src/NGettext/Loaders/BigEndianBinaryReader.cs create mode 100644 src/NGettext/Loaders/ReadOnlyStreamWrapper.cs diff --git a/src/NGettext/Loaders/BigEndianBinaryReader.cs b/src/NGettext/Loaders/BigEndianBinaryReader.cs new file mode 100644 index 0000000..0d3b79b --- /dev/null +++ b/src/NGettext/Loaders/BigEndianBinaryReader.cs @@ -0,0 +1,217 @@ +using System; +using System.IO; +using System.Text; + +namespace NGettext.Loaders +{ + /// + /// Reads primitive data types as binary values represented in big endian byte order. + /// + public class BigEndianBinaryReader : BinaryReader + { + private byte[] _Buffer = new byte[16]; + + /// + /// Initializes a new instance of the class based on the + /// supplied stream and using System.Text.UTF8Encoding. + /// + /// + public BigEndianBinaryReader(Stream input) : base(input) + { + } + + /// + /// Initializes a new instance of the class based on the + /// supplied stream and a specific character encoding. + /// + /// + /// + public BigEndianBinaryReader(Stream input, Encoding encoding) : base(input, encoding) + { + } + + /// + /// Reads a 2-byte signed integer from the current + /// stream and advances the current position of the stream by two bytes. + /// + /// + /// A 2-byte signed integer read from the current stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + public override short ReadInt16() + { + this._FillBuffer(2); + return (short)(this._Buffer[1] | this._Buffer[0] << 8); + } + + /// + /// Reads a 2-byte unsigned integer from the current + /// stream using little-endian encoding and advances the position of the stream by two bytes. + /// + /// + /// A 2-byte unsigned integer read from this stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + [CLSCompliant(false)] + public override ushort ReadUInt16() + { + this._FillBuffer(2); + return (ushort)(this._Buffer[1] | this._Buffer[0] << 8); + } + + /// + /// Reads a 4-byte signed integer from the current + /// stream and advances the current position of the stream by four bytes. + /// + /// + /// A 4-byte signed integer read from the current stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + public override int ReadInt32() + { + this._FillBuffer(4); + return (int)(this._Buffer[3] | this._Buffer[2] << 8 | this._Buffer[1] << 16 | this._Buffer[0] << 24); + } + + /// + /// Reads a 4-byte unsigned integer from the current + /// stream and advances the position of the stream by four bytes. + /// + /// + /// A 4-byte unsigned integer read from this stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + [CLSCompliant(false)] + public override uint ReadUInt32() + { + this._FillBuffer(4); + return (uint)(this._Buffer[3] | this._Buffer[2] << 8 | this._Buffer[1] << 16 | this._Buffer[0] << 24); + } + + /// + /// Reads an 8-byte signed integer from the current + /// stream and advances the current position of the stream by eight bytes. + /// + /// + /// An 8-byte signed integer read from the current stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + public override long ReadInt64() + { + this._FillBuffer(8); + if (BitConverter.IsLittleEndian) + { + // We don't need to reverse bytes on big-endian machine as BitConverter respects machine endianness + Array.Reverse(this._Buffer, 0, 8); + } + return BitConverter.ToInt64(this._Buffer, 0); + } + + /// + /// Reads an 8-byte unsigned integer from the current + /// stream and advances the position of the stream by eight bytes. + /// + /// + /// An 8-byte unsigned integer read from this stream. + /// + /// The end of the stream is reached. + /// An I/O error occurs. + /// The stream is closed. + /// 2 + [CLSCompliant(false)] + public override ulong ReadUInt64() + { + this._FillBuffer(8); + if (BitConverter.IsLittleEndian) + { + // We don't need to reverse bytes on big-endian machine as BitConverter respects machine endianness + Array.Reverse(this._Buffer, 0, 8); + } + return BitConverter.ToUInt64(this._Buffer, 0); + } + + /// + /// Reads a 4-byte floating point value from the current + /// stream and advances the current position of the stream by four bytes. + /// + /// + /// A 4-byte floating point value read from the current stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + public override float ReadSingle() + { + this._FillBuffer(4); + if (BitConverter.IsLittleEndian) + { + // We don't need to reverse bytes on big-endian machine as BitConverter respects machine endianness + Array.Reverse(this._Buffer, 0, 4); + } + return BitConverter.ToSingle(this._Buffer, 0); + } + + /// + /// Reads an 8-byte floating point value from the current + /// stream and advances the current position of the stream by eight bytes. + /// + /// + /// An 8-byte floating point value read from the current stream. + /// + /// The end of the stream is reached. + /// The stream is closed. + /// An I/O error occurs. + /// 2 + public override double ReadDouble() + { + this._FillBuffer(8); + if (BitConverter.IsLittleEndian) + { + // We don't need to reverse bytes on big-endian machine as BitConverter respects machine endianness + Array.Reverse(this._Buffer, 0, 8); + } + return BitConverter.ToDouble(this._Buffer, 0); + } + + + private void _FillBuffer(int numBytes) + { + if (numBytes < 2 || numBytes > this._Buffer.Length) + { + throw new ArgumentOutOfRangeException("numBytes"); + } + int bytesRead = 0; + int n = 0; + + var stream = this.BaseStream; + if (stream == null) + throw new ObjectDisposedException("Base stream closed."); + + do + { + n = stream.Read(this._Buffer, bytesRead, numBytes - bytesRead); + if (n == 0) + { + throw new EndOfStreamException("Unexpected End Of File."); + } + bytesRead += n; + } while (bytesRead < numBytes); + } + } +} diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index ce80c0f..6c18cf6 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -15,7 +15,7 @@ public class MoFileParser /// /// MO file format magic number. /// - public const uint MO_FILE_MAGIC = 0x950412de; + private const uint MO_FILE_MAGIC = 0x950412de; private struct StringOffsetTable { @@ -53,65 +53,81 @@ public Dictionary GetTranslations(Stream stream) throw new ArgumentException("Stream can not be null of less than 20 bytes long."); } - var reader = new BinaryReader(stream); - var magicNumber = reader.ReadUInt32(); - - if (magicNumber != MO_FILE_MAGIC) + var reader = new BinaryReader(new ReadOnlyStreamWrapper(stream)); + try { - throw new ArgumentException("Invalid stream: can not find MO file magic number."); - } + var magicNumber = reader.ReadUInt32(); + if (magicNumber != MO_FILE_MAGIC) + { + // System.IO.BinaryReader does not respect machine endianness and always uses little-endian + // So we need to detect and read big-endian files by ourselves + if (_ReverseBytes(magicNumber) == MO_FILE_MAGIC) + { + Trace.WriteLine("Big Endian file detected. Switching readers...", "NGettext"); + reader.Close(); + reader = new BigEndianBinaryReader(new ReadOnlyStreamWrapper(stream)); + } + else + { + throw new ArgumentException("Invalid stream: can not find MO file magic number."); + } + } - var revision = reader.ReadUInt32(); - Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", revision >> 16, revision & 0xffff), "NGettext"); + var revision = reader.ReadUInt32(); + Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", revision >> 16, revision & 0xffff), "NGettext"); - if ((revision >> 16) > 1) - { - throw new Exception(String.Format("Unsupported MO file major revision: {0}.", revision >> 16)); - } + if ((revision >> 16) > 1) + { + throw new Exception(String.Format("Unsupported MO file major revision: {0}.", revision >> 16)); + } - var stringCount = reader.ReadInt32(); - var originalTableOffset = reader.ReadInt32(); - var translationTableOffset = reader.ReadInt32(); + var stringCount = reader.ReadInt32(); + var originalTableOffset = reader.ReadInt32(); + var translationTableOffset = reader.ReadInt32(); - // We don't support hash tables and system dependent segments. + // We don't support hash tables and system dependent segments. - Trace.WriteLine(String.Format("MO File contains {0} strings.", stringCount), "NGettext"); + Trace.WriteLine(String.Format("MO File contains {0} strings.", stringCount), "NGettext"); + var originalTable = new StringOffsetTable[stringCount]; + var translationTable = new StringOffsetTable[stringCount]; + Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); - var originalTable = new StringOffsetTable[stringCount]; - var translationTable = new StringOffsetTable[stringCount]; + reader.BaseStream.Seek(originalTableOffset, SeekOrigin.Begin); + for (int i = 0; i < stringCount; i++) + { + originalTable[i].Length = reader.ReadInt32(); + originalTable[i].Offset = reader.ReadInt32(); + } - Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); + reader.BaseStream.Seek(translationTableOffset, SeekOrigin.Begin); + for (int i = 0; i < stringCount; i++) + { + translationTable[i].Length = reader.ReadInt32(); + translationTable[i].Offset = reader.ReadInt32(); + } - reader.BaseStream.Seek(originalTableOffset, SeekOrigin.Begin); - for (int i = 0; i < stringCount; i++) - { - originalTable[i].Length = reader.ReadInt32(); - originalTable[i].Offset = reader.ReadInt32(); - } - reader.BaseStream.Seek(translationTableOffset, SeekOrigin.Begin); - for (int i = 0; i < stringCount; i++) - { - translationTable[i].Length = reader.ReadInt32(); - translationTable[i].Offset = reader.ReadInt32(); - } + var dict = new Dictionary(stringCount); + for (int i = 0; i < stringCount; i++) + { + var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); + var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); - var dict = new Dictionary(stringCount); + dict.Add(originalStrings[0], translatedStrings); + } - for (int i = 0; i < stringCount; i++) - { - var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); - var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); + Trace.WriteLine("String parsing completed.", "NGettext"); - dict.Add(originalStrings[0], translatedStrings); - } - - Trace.WriteLine("String parsing completed.", "NGettext"); + return dict; - return dict; + } + finally + { + reader.Close(); + } } private string[] _ReadStrings(BinaryReader reader, int offset, int length) @@ -120,5 +136,11 @@ private string[] _ReadStrings(BinaryReader reader, int offset, int length) var stringBytes = reader.ReadBytes(length); return this.Encoding.GetString(stringBytes).Split('\0'); } + + private static uint _ReverseBytes(uint value) + { + return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 | + (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; + } } } \ No newline at end of file diff --git a/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs b/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs new file mode 100644 index 0000000..81dd41f --- /dev/null +++ b/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs @@ -0,0 +1,131 @@ +using System; +using System.IO; + +namespace NGettext.Loaders +{ + public sealed class ReadOnlyStreamWrapper : Stream + { + public Stream BaseStream { get; private set; } + + private bool _IsClosed = false; + + public ReadOnlyStreamWrapper(Stream baseStream) + { + if (baseStream == null) + throw new ArgumentNullException("baseStream"); + + this.BaseStream = baseStream; + } + + public override void Flush() + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override long Seek(long offset, SeekOrigin origin) + { + this._CheckIsClosed(); + return this.BaseStream.Seek(offset, origin); + } + + public override void SetLength(long value) + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override int Read(byte[] buffer, int offset, int count) + { + this._CheckIsClosed(); + return this.BaseStream.Read(buffer, offset, count); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override bool CanRead + { + get { return !this._IsClosed && this.BaseStream.CanRead; } + } + + public override bool CanSeek + { + get { return !this._IsClosed && this.BaseStream.CanSeek; } + } + + public override bool CanWrite + { + get { return false; } + } + + public override long Length + { + get + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + } + + public override long Position + { + get + { + this._CheckIsClosed(); + return this.BaseStream.Position; + } + set + { + this._CheckIsClosed(); + this.BaseStream.Position = value; + } + } + + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + this._CheckIsClosed(); + return base.BeginRead(buffer, offset, count, callback, state); + } + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override int EndRead(IAsyncResult asyncResult) + { + this._CheckIsClosed(); + return base.EndRead(asyncResult); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override int ReadByte() + { + this._CheckIsClosed(); + return base.ReadByte(); + } + + public override void WriteByte(byte value) + { + throw new InvalidOperationException("Stream is in read-only mode."); + } + + public override void Close() + { + if (!this._IsClosed) + { + this._IsClosed = true; + } + } + + private void _CheckIsClosed() + { + if (this._IsClosed) + throw new ObjectDisposedException(null, "Stream closed."); + } + } +} \ No newline at end of file diff --git a/src/NGettext/NGettext.csproj b/src/NGettext/NGettext.csproj index 253e587..fbbc885 100644 --- a/src/NGettext/NGettext.csproj +++ b/src/NGettext/NGettext.csproj @@ -46,6 +46,8 @@ + + From b8eb5383584b84402f6cd23a2ef22b3b6c8f39e3 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 May 2015 17:08:28 +0300 Subject: [PATCH 05/55] Big-endian MO file test. --- src/NGettext.Tests/Loaders/MoFileParserTest.cs | 17 +++++++++++++++++ src/NGettext.Tests/NGettext.Tests.csproj | 3 +++ .../locales/ru_RU/LC_MESSAGES/TestBigEndian.mo | Bin 0 -> 772 bytes 3 files changed, 20 insertions(+) create mode 100644 src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/TestBigEndian.mo diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 0335490..4c61b71 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -31,5 +31,22 @@ public void TestParsing() Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); } } + + [Test] + public void TestBigEndianParsing() + { + var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); + using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "TestBigEndian.mo"))) + { + var parser = new MoFileParser(); + var dict = parser.GetTranslations(stream); + + Assert.AreEqual(new[] { "тест" }, dict["test"]); + Assert.AreEqual(new[] { "тест2" }, dict["test2"]); + Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); + Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + } + } } } \ No newline at end of file diff --git a/src/NGettext.Tests/NGettext.Tests.csproj b/src/NGettext.Tests/NGettext.Tests.csproj index b726e9e..04405b8 100644 --- a/src/NGettext.Tests/NGettext.Tests.csproj +++ b/src/NGettext.Tests/NGettext.Tests.csproj @@ -68,6 +68,9 @@ PreserveNewest + + PreserveNewest + diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/TestBigEndian.mo b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/TestBigEndian.mo new file mode 100644 index 0000000000000000000000000000000000000000..8df7dd67da87a9577e9ebb7dfb3f6e37d71d043f GIT binary patch literal 772 zcmZ`%&ubJh7)|Rcbp#I{Jcx(%U}=zOGAnk?b`-3w6n1qfqxZO*PDf@lOOh4E^R!RE8t&%GYBm{pYUtoCD5ONj{|=NX23sy7XXU@Kig+b z%jf$#QV~46xpwNI<29$Ot50P(k$w~TM~EJ?C%B*Lp;Lb>E$W#3zUn%<-J^Gvv1zUa zzI9VMABz1+?2ObllMY&VH_cSAqXxNgv~82LN3RbPOXFPNpmRH>8%C8zdP6!TaL9N_ z*%itzW5z{&?K}$^10&s04^lttUmsr+yixgD(mEPXrsoDmw4_dkGEp>EvJbkw-QJwP zHow4v4gWhd9D6i?`Tip=4l Date: Thu, 14 May 2015 17:13:39 +0300 Subject: [PATCH 06/55] Documentation fix for ReadOnlyStreamWrapper. --- src/NGettext/Loaders/ReadOnlyStreamWrapper.cs | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs b/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs index 81dd41f..18853fd 100644 --- a/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs +++ b/src/NGettext/Loaders/ReadOnlyStreamWrapper.cs @@ -3,12 +3,22 @@ namespace NGettext.Loaders { + /// + /// Stream wrapper that prevents closing and writing to underlying stream. + /// public sealed class ReadOnlyStreamWrapper : Stream { + /// + /// Gets or sets the underlying stream. + /// public Stream BaseStream { get; private set; } private bool _IsClosed = false; + /// + /// Initializes a new instance of the class that wraps specified underlying stream. + /// + /// public ReadOnlyStreamWrapper(Stream baseStream) { if (baseStream == null) @@ -17,48 +27,102 @@ public ReadOnlyStreamWrapper(Stream baseStream) this.BaseStream = baseStream; } + /// + /// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + /// An I/O error occurs. 2 public override void Flush() { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// When overridden in a derived class, sets the position within the current stream. + /// + /// + /// The new position within the current stream. + /// + /// A byte offset relative to the parameter. A value of type indicating the reference point used to obtain the new position. An I/O error occurs. The stream does not support seeking, such as if the stream is constructed from a pipe or console output. Methods were called after the stream was closed. 1 public override long Seek(long offset, SeekOrigin origin) { this._CheckIsClosed(); return this.BaseStream.Seek(offset, origin); } + /// + /// When overridden in a derived class, sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. An I/O error occurs. The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. Methods were called after the stream was closed. 2 public override void SetLength(long value) { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between and ( + - 1) replaced by the bytes read from the current source. The zero-based byte offset in at which to begin storing the data read from the current stream. The maximum number of bytes to be read from the current stream. The sum of and is larger than the buffer length. is null. or is negative. An I/O error occurs. The stream does not support reading. Methods were called after the stream was closed. 1 public override int Read(byte[] buffer, int offset, int count) { this._CheckIsClosed(); return this.BaseStream.Read(buffer, offset, count); } + /// + /// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies bytes from to the current stream. The zero-based byte offset in at which to begin copying bytes to the current stream. The number of bytes to be written to the current stream. 1 public override void Write(byte[] buffer, int offset, int count) { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// When overridden in a derived class, gets a value indicating whether the current stream supports reading. + /// + /// + /// true if the stream supports reading; otherwise, false. + /// + /// 1 public override bool CanRead { get { return !this._IsClosed && this.BaseStream.CanRead; } } + /// + /// When overridden in a derived class, gets a value indicating whether the current stream supports seeking. + /// + /// + /// true if the stream supports seeking; otherwise, false. + /// + /// 1 public override bool CanSeek { get { return !this._IsClosed && this.BaseStream.CanSeek; } } + /// + /// When overridden in a derived class, gets a value indicating whether the current stream supports writing. + /// + /// + /// true if the stream supports writing; otherwise, false. + /// + /// 1 public override bool CanWrite { get { return false; } } + /// + /// When overridden in a derived class, gets the length in bytes of the stream. + /// + /// + /// A long value representing the length of the stream in bytes. + /// + /// A class derived from Stream does not support seeking. Methods were called after the stream was closed. 1 public override long Length { get @@ -67,6 +131,13 @@ public override long Length } } + /// + /// When overridden in a derived class, gets or sets the position within the current stream. + /// + /// + /// The current position within the stream. + /// + /// An I/O error occurs. The stream does not support seeking. Methods were called after the stream was closed. 1 public override long Position { get @@ -81,39 +152,79 @@ public override long Position } } + /// + /// Begins an asynchronous read operation. + /// + /// + /// An that represents the asynchronous read, which could still be pending. + /// + /// The buffer to read the data into. The byte offset in at which to begin writing data read from the stream. The maximum number of bytes to read. An optional asynchronous callback, to be called when the read is complete. A user-provided object that distinguishes this particular asynchronous read request from other requests. Attempted an asynchronous read past the end of the stream, or a disk error occurs. One or more of the arguments is invalid. Methods were called after the stream was closed. The current Stream implementation does not support the read operation. 2 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { this._CheckIsClosed(); return base.BeginRead(buffer, offset, count, callback, state); } + /// + /// Begins an asynchronous write operation. + /// + /// + /// An IAsyncResult that represents the asynchronous write, which could still be pending. + /// + /// The buffer to write data from. The byte offset in from which to begin writing. The maximum number of bytes to write. An optional asynchronous callback, to be called when the write is complete. A user-provided object that distinguishes this particular asynchronous write request from other requests. Attempted an asynchronous write past the end of the stream, or a disk error occurs. One or more of the arguments is invalid. Methods were called after the stream was closed. The current Stream implementation does not support the write operation. 2 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// Waits for the pending asynchronous read to complete. + /// + /// + /// The number of bytes read from the stream, between zero (0) and the number of bytes you requested. Streams return zero (0) only at the end of the stream, otherwise, they should block until at least one byte is available. + /// + /// The reference to the pending asynchronous request to finish. is null. did not originate from a method on the current stream. The stream is closed or an internal error has occurred.2 public override int EndRead(IAsyncResult asyncResult) { this._CheckIsClosed(); return base.EndRead(asyncResult); } + /// + /// Ends an asynchronous write operation. + /// + /// A reference to the outstanding asynchronous I/O request. is null. did not originate from a method on the current stream. The stream is closed or an internal error has occurred.2 public override void EndWrite(IAsyncResult asyncResult) { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. + /// + /// + /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. + /// + /// The stream does not support reading. Methods were called after the stream was closed. 2 public override int ReadByte() { this._CheckIsClosed(); return base.ReadByte(); } + /// + /// Writes a byte to the current position in the stream and advances the position within the stream by one byte. + /// + /// The byte to write to the stream. An I/O error occurs. The stream does not support writing, or the stream is already closed. Methods were called after the stream was closed. 2 public override void WriteByte(byte value) { throw new InvalidOperationException("Stream is in read-only mode."); } + /// + /// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. + /// + /// 1 public override void Close() { if (!this._IsClosed) From 53880080979b0ed2069f9a6bb738681254632e3b Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 May 2015 17:54:04 +0300 Subject: [PATCH 07/55] Readme updated. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0b2786..58c0068 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This implementation loads translations directly from gettext *.mo files (no need NGettext currently not supports *.mo file headers (stored in mo file plural formulas, encoding, etc.). It uses precompiled plural formulas and supports custom plural formulas passed through API. -It only supports little-endian MO files (witch produce most of popular platforms). +It supports both little-endian and big-endian MO files. From c6c28a02ddd7d6eb166dc5c2c74f81b706c5056b Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 16:56:16 +0300 Subject: [PATCH 08/55] Test added for empty translation ID check. --- src/NGettext.Tests/BaseCatalogTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index 884922c..222debb 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -29,11 +29,13 @@ public void TestGetString() t.Translations.Add("key1", new[] { "value1" }); t.Translations.Add("key2", new[] { "value2" }); t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); + t.Translations.Add("", new[] { "emptyIdValue" }); Assert.AreEqual("value1", t.GetString("key1")); Assert.AreEqual("value2", t.GetString("key2")); Assert.AreEqual("value3plural1", t.GetString("key3")); Assert.AreEqual("notFoundKey2", t.GetString("notFoundKey2")); + Assert.AreEqual("", t.GetString("")); } [Test] From b26a12b0fee08fc520600b67952a6522d7c6419c Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 17:22:57 +0300 Subject: [PATCH 09/55] Culture-specific message formatting. --- README.md | 21 +++++++++++++- src/NGettext.Tests/BaseCatalogTest.cs | 40 +++++++++++++++++++++++++++ src/NGettext/BaseCatalog.cs | 8 +++--- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 58c0068..cac2dda 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,20 @@ Now you can use NGettext in your code: +### Culture-specific message formatting + +```csharp + // All translation methods support String.Format optional arguments + catalog.GetString("Hello, {0}!", "World"); + + // Catalog's current locale will be used to format messages correctly + catalog.GetString("Here's a number: {0}!", 1.23); + // Will return "Here's a number: 1.23!" for en_US locale + // But something like this will be returned for ru_RU locale with Russian translation: " : 1,23!" +``` + + + ### Plural forms ```csharp @@ -100,6 +114,11 @@ Now you can use NGettext in your code: catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", 5, 5); // Returns translated plural massage: "You have 5 apples." (for en_US locale) // First 5 used in plural forms determination; second in String.Format method + + + // Example plural forms usage for fractional numbers: + catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", (long)1.23, 1.23); + // Internal String.Format will be used in context of catalog's locale and formats objects respectively ``` @@ -132,7 +151,7 @@ Now you can use NGettext in your code: ```csharp Stream moFileStream = File.OpenRead("path/to/domain.mo"); - ICatalog catalog = new Catalog(moFileStream); + ICatalog catalog = new Catalog(moFileStream, CultureInfo.CreateSpecificCulture("en-US")); ``` diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index 222debb..2cd2a76 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -48,6 +48,16 @@ public void TestGetStringFormat() Assert.AreEqual("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); } + [Test] + public void TestGetStringFormatCulture() + { + var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); + var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); + + Assert.AreEqual("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); + Assert.AreEqual("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); + } + #endregion #region GetPluralString @@ -99,6 +109,16 @@ public void TestGetPluralStringInternational() Assert.AreEqual("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); } + [Test] + public void TestGetPluralStringFormatCulture() + { + var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); + var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); + + Assert.AreEqual("Foo 1.23", catalogEn.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.AreEqual("Foo 1,23", catalogRu.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + } + #endregion #region GetParticularString @@ -126,6 +146,16 @@ public void TestGetParticularStringFormat() Assert.AreEqual("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); } + [Test] + public void TestGetParticularStringFormatCulture() + { + var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); + var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); + + Assert.AreEqual("Foo 1.23", catalogEn.GetParticularString("context", "Foo {0}", 1.23)); + Assert.AreEqual("Foo 1,23", catalogRu.GetParticularString("context", "Foo {0}", 1.23)); + } + #endregion #region GetParticularPluralString @@ -154,6 +184,16 @@ public void TestGetParticularPluralStringFormat() Assert.AreEqual("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); } + [Test] + public void TestGetParticularPluralStringFormatCulture() + { + var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); + var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); + + Assert.AreEqual("Foo 1.23", catalogEn.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.AreEqual("Foo 1,23", catalogRu.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); + } + #endregion #region *Default methods diff --git a/src/NGettext/BaseCatalog.cs b/src/NGettext/BaseCatalog.cs index 3d24160..764c4c9 100644 --- a/src/NGettext/BaseCatalog.cs +++ b/src/NGettext/BaseCatalog.cs @@ -67,7 +67,7 @@ public virtual string GetString(string text) /// Translated text. public virtual string GetString(string text, params object[] args) { - return String.Format(this.GetStringDefault(text, text), args); + return String.Format(this.CultureInfo, this.GetStringDefault(text, text), args); } /// @@ -94,7 +94,7 @@ public virtual string GetPluralString(string text, string pluralText, long n) /// Translated text. public virtual string GetPluralString(string text, string pluralText, long n, params object[] args) { - return String.Format(this.GetPluralStringDefault(text, text, pluralText, n), args); + return String.Format(this.CultureInfo, this.GetPluralStringDefault(text, text, pluralText, n), args); } /// @@ -119,7 +119,7 @@ public virtual string GetParticularString(string context, string text) /// Translated text. public virtual string GetParticularString(string context, string text, params object[] args) { - return String.Format(this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); + return String.Format(this.CultureInfo, this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); } /// @@ -148,7 +148,7 @@ public virtual string GetParticularPluralString(string context, string text, str /// Translated text. public virtual string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args) { - return String.Format(this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); + return String.Format(this.CultureInfo, this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); } #endregion From dc6f47af99da9b4d6610b665c859a1aa0207106d Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 17:30:29 +0300 Subject: [PATCH 10/55] Unit test project namespace fix. --- src/NGettext.Tests/BaseCatalogTest.cs | 5 ++--- src/NGettext.Tests/CatalogTest.cs | 4 +--- src/NGettext.Tests/Loaders/MoFileParserTest.cs | 3 +-- src/NGettext.Tests/Plural/PluralFormProcessorTest.cs | 2 +- src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs | 4 +--- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index 2cd2a76..84f708c 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -6,10 +6,9 @@ using NUnit.Framework; -using NGettext; -using Tests.Stabs; +using NGettext.Tests.Stabs; -namespace Tests +namespace NGettext.Tests { [TestFixture] public class BaseCatalogTest diff --git a/src/NGettext.Tests/CatalogTest.cs b/src/NGettext.Tests/CatalogTest.cs index 15c64a6..9f1da72 100644 --- a/src/NGettext.Tests/CatalogTest.cs +++ b/src/NGettext.Tests/CatalogTest.cs @@ -8,9 +8,7 @@ using NUnit.Framework; -using NGettext; - -namespace Tests +namespace NGettext.Tests { [TestFixture] public class CatalogTest diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 4c61b71..88524dc 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -7,10 +7,9 @@ using NUnit.Framework; -using NGettext; using NGettext.Loaders; -namespace Tests.Loaders +namespace NGettext.Tests.Loaders { [TestFixture] public class MoFileParserTest diff --git a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs b/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs index 92b0a34..a1b4925 100644 --- a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs +++ b/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs @@ -8,7 +8,7 @@ using NGettext.Plural; -namespace Tests.Plural +namespace NGettext.Tests.Plural { [TestFixture] public class PluralFormProcessorTest diff --git a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs index 79765e5..0927121 100644 --- a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs +++ b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs @@ -4,9 +4,7 @@ using System.Text; using System.Globalization; -using NGettext; - -namespace Tests.Stabs +namespace NGettext.Tests.Stabs { public class EmptyBaseCatalog : BaseCatalog { From f8ff661ea2001801885d71911b161c89061bbc53 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 17:34:30 +0300 Subject: [PATCH 11/55] Readme encoding fix. [ci skip] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cac2dda..466f2b4 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Now you can use NGettext in your code: // Catalog's current locale will be used to format messages correctly catalog.GetString("Here's a number: {0}!", 1.23); // Will return "Here's a number: 1.23!" for en_US locale - // But something like this will be returned for ru_RU locale with Russian translation: " : 1,23!" + // But something like this will be returned for ru_RU locale with Russian translation: "А вот и номер: 1,23!" ``` @@ -113,7 +113,7 @@ Now you can use NGettext in your code: catalog.GetPluralString("You have {0} apple.", "You have {0} apples.", 5, 5); // Returns translated plural massage: "You have 5 apples." (for en_US locale) - // First 5 used in plural forms determination; second in String.Format method + // First “5” used in plural forms determination; second — in String.Format method // Example plural forms usage for fractional numbers: From 5530c3f3ed6ffed9aecd289fc2c0bc0c185f0629 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 19:13:31 +0300 Subject: [PATCH 12/55] MoFileParser: headers support, automatic encoding detection. --- .../Loaders/MoFileParserTest.cs | 55 +++++++--- src/NGettext.Tests/NGettext.Tests.csproj | 8 +- .../locales/ru_RU/LC_MESSAGES/Test.po | 3 + .../{TestBigEndian.mo => Test_BigEndian.mo} | Bin .../locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo | Bin 0 -> 724 bytes .../locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po | 36 +++++++ src/NGettext/Catalog.cs | 13 ++- src/NGettext/Loaders/MoFileParser.cs | 102 +++++++++++++++--- 8 files changed, 186 insertions(+), 31 deletions(-) rename src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/{TestBigEndian.mo => Test_BigEndian.mo} (100%) create mode 100644 src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo create mode 100644 src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 88524dc..bc251e8 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -21,13 +21,8 @@ public void TestParsing() using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test.mo"))) { var parser = new MoFileParser(); - var dict = parser.GetTranslations(stream); - - Assert.AreEqual(new[] { "тест" }, dict["test"]); - Assert.AreEqual(new[] { "тест2" }, dict["test2"]); - Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + parser.Parse(stream); + this._TestLoadedTranslation(parser.Translations); } } @@ -35,17 +30,49 @@ public void TestParsing() public void TestBigEndianParsing() { var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); - using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "TestBigEndian.mo"))) + using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test_BigEndian.mo"))) + { + var parser = new MoFileParser(); + parser.Parse(stream); + this._TestLoadedTranslation(parser.Translations); + } + } + + [Test] + public void TestAutoEncoding() + { + var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); + using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test_KOI8-R.mo"))) { var parser = new MoFileParser(); - var dict = parser.GetTranslations(stream); + parser.Parse(stream); + this._TestLoadedTranslation(parser.Translations); + } + } - Assert.AreEqual(new[] { "тест" }, dict["test"]); - Assert.AreEqual(new[] { "тест2" }, dict["test2"]); - Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + [Test] + public void TestManualEncoding() + { + var localesDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestResources", "locales"); + using (var stream = File.OpenRead(Path.Combine(localesDir, "ru_RU", "LC_MESSAGES", "Test_KOI8-R.mo"))) + { + var parser = new MoFileParser() + { + Encoding = Encoding.GetEncoding("KOI8-R"), + DetectEncoding = false, + }; + parser.Parse(stream); + this._TestLoadedTranslation(parser.Translations); } } + + private void _TestLoadedTranslation(IDictionary dict) + { + Assert.AreEqual(new[] { "тест" }, dict["test"]); + Assert.AreEqual(new[] { "тест2" }, dict["test2"]); + Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); + Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + } } } \ No newline at end of file diff --git a/src/NGettext.Tests/NGettext.Tests.csproj b/src/NGettext.Tests/NGettext.Tests.csproj index 04405b8..69a58c2 100644 --- a/src/NGettext.Tests/NGettext.Tests.csproj +++ b/src/NGettext.Tests/NGettext.Tests.csproj @@ -68,7 +68,13 @@ PreserveNewest - + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po index 835a635..2857421 100644 --- a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po +++ b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po @@ -18,6 +18,9 @@ msgstr "тест" msgid "test2" msgstr "тест2" +msgid "test3" +msgstr "" + msgid "{0} minute" msgid_plural "{0} minutes" msgstr[0] "{0} минута" diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/TestBigEndian.mo b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/TestBigEndian.mo rename to src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo new file mode 100644 index 0000000000000000000000000000000000000000..a1aa11bc37e65cc645cf00ccbda5421ceefccfa5 GIT binary patch literal 724 zcmZWmF>ezw6gD(4TqOnuCM4XURV`$&FNg-G2NG>TQ4<(I|AJ>85l_;F$54vRjnh z#Egsj+Eo@a21eRbPcy&ke;;2Hyixhu(mL9oZ7&S0XiJ?=WU6Ri$r0#ItFtwKZGMeK z8~%4_XnQ_}{r)4ak8_#nCLTPN#wwR=@3b1UH#hqEyUNflJt&5mP6ci}%3RdVCr0M< zUSUR7U_B1fCiNz+(qt7vFLOqcgp-w(N-(mNa8AgbRYrt&RF>OG{KrDplN%(cP-A2r zW=yB2{a|Ip58y<^gft^m9-Nf*!>`BX!Qn~C|CMo&;izu-%je_o<;QTtA^kB=(Qi{S B$nXFF literal 0 HcmV?d00001 diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po new file mode 100644 index 0000000..ba23752 --- /dev/null +++ b/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po @@ -0,0 +1,36 @@ +msgid "" +msgstr "" +"Project-Id-Version: NGettext test translation file\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-06 01:37+0200\n" +"PO-Revision-Date: 2012-09-06 17:18+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=KOI8-R\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)" +">=2)&&((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2));\n" + +msgid "test" +msgstr "" + +msgid "test2" +msgstr "2" + +msgid "test3" +msgstr "" + +msgid "{0} minute" +msgid_plural "{0} minutes" +msgstr[0] "{0} " +msgstr[1] "{0} " +msgstr[2] "{0} " + +msgctxt "context1" +msgid "test3" +msgstr "31" + +msgctxt "context2" +msgid "test3" +msgstr "32" diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index 1dbf501..2447a7f 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -140,21 +140,26 @@ public void Load(string path) } /// - /// Load translations from given MO file stream using given encoding (UTF-8 encoding by default). + /// Load translations from given MO file stream using given encoding. /// + /// + /// By default, parser will try to detect file encoding automatically with fallback to UTF-8 encoding. + /// If you specify any encoding in this method, auto-detect will be turned off and given encoding will be used instead. + /// /// Stream that contain binary data in the MO file format - /// File encoding (UTF-8 by default) + /// File encoding (auto detect by default) public void Load(Stream moStream, Encoding encoding = null) { var parser = new MoFileParser(); if (encoding != null) { + parser.DetectEncoding = false; parser.Encoding = encoding; } - var translations = parser.GetTranslations(moStream); + parser.Parse(moStream); - this.Translations = translations; + this.Translations = parser.Translations; } private string _FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index 6c18cf6..d328485 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -3,6 +3,7 @@ using System.Text; using System.Diagnostics; using System.IO; +using System.Net.Mime; namespace NGettext.Loaders { @@ -17,6 +18,8 @@ public class MoFileParser /// private const uint MO_FILE_MAGIC = 0x950412de; + private const ushort MAX_SUPPORTED_VERSION = 1; + private struct StringOffsetTable { public int Length; @@ -26,26 +29,58 @@ private struct StringOffsetTable /// /// Current encoding for decoding all strings in given MO file. /// + /// + /// Default value is UTF-8 as it is compatible with required by specifications us-ascii. + /// This value could be changed when DetectEncoding property is set to True and the MO file + /// contains a valid charset name in the Content-Type header. + /// public Encoding Encoding { get; set; } + /// + /// Gets or sets a value that indicates whenever the parser can detect file encoding using the Content-Type MIME header. + /// + public bool DetectEncoding { get; set; } + + /// + /// Gets a value that indicates whenever loaded file was in the big-endian format. + /// + public bool IsBigEndian { get; protected set; } + + /// + /// Gets parsed file's format revision. + /// + public Version FormatRevision { get; protected set; } + + /// + /// Gets parsed file's metadata. + /// + public Dictionary Headers { get; protected set; } + + /// + /// Gets parsed file's translation strings. + /// + public Dictionary Translations { get; protected set; } + /// /// Initializes a new instance of the class. /// public MoFileParser() { this.Encoding = Encoding.UTF8; + this.DetectEncoding = true; + this._Init(); } /// - /// Read and load all translation strings from given MO file stream. + /// Parses a GNU MO file from the given stream and loads all available data. /// /// /// http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html /// /// Stream that contain binary data in the MO file format - /// Raw translations - public Dictionary GetTranslations(Stream stream) + public void Parse(Stream stream) { + this._Init(); Trace.WriteLine("Trying to parse a MO file stream...", "NGettext"); if (stream == null || stream.Length < 20) @@ -64,6 +99,7 @@ public Dictionary GetTranslations(Stream stream) if (_ReverseBytes(magicNumber) == MO_FILE_MAGIC) { Trace.WriteLine("Big Endian file detected. Switching readers...", "NGettext"); + this.IsBigEndian = true; reader.Close(); reader = new BigEndianBinaryReader(new ReadOnlyStreamWrapper(stream)); } @@ -73,12 +109,14 @@ public Dictionary GetTranslations(Stream stream) } } - var revision = reader.ReadUInt32(); - Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", revision >> 16, revision & 0xffff), "NGettext"); + var revision = reader.ReadInt32(); + this.FormatRevision = new Version(revision >> 16, revision & 0xffff); - if ((revision >> 16) > 1) + Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", this.FormatRevision.Major, this.FormatRevision.Minor), "NGettext"); + + if (this.FormatRevision.Major > MAX_SUPPORTED_VERSION) { - throw new Exception(String.Format("Unsupported MO file major revision: {0}.", revision >> 16)); + throw new Exception(String.Format("Unsupported MO file major revision: {0}.", this.FormatRevision.Major)); } var stringCount = reader.ReadInt32(); @@ -109,20 +147,52 @@ public Dictionary GetTranslations(Stream stream) } - var dict = new Dictionary(stringCount); - for (int i = 0; i < stringCount; i++) { var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); - dict.Add(originalStrings[0], translatedStrings); + if (originalStrings.Length == 0 || translatedStrings.Length == 0) continue; + + if (originalStrings[0].Length == 0) + { + // MO file metadata processing + foreach (var headerText in translatedStrings[0].Split(new []{'\n', '\r'}, StringSplitOptions.RemoveEmptyEntries)) + { + var header = headerText.Split(new [] {':'}, 2); + if (header.Length == 2) + { + this.Headers.Add(header[0], header[1].Trim()); + } + } + + if (this.DetectEncoding && this.Headers.ContainsKey("Content-Type")) + { + try + { + var contentType = new ContentType(this.Headers["Content-Type"]); + if (!String.IsNullOrEmpty(contentType.CharSet)) + { + this.Encoding = Encoding.GetEncoding(contentType.CharSet); + Trace.WriteLine(String.Format("File encoding switched to \"{0}\" (\"{1}\" requested).", this.Encoding, contentType.CharSet), "NGettext"); + } + } + catch (Exception exception) + { + Trace.WriteLine(String.Format("Unable to change parser encoding using the Content-Type header: \"{0}\".", exception.Message), "NGettext"); + } + } + if (this.Headers.ContainsKey("Plural-Forms")) + { + //TODO: Plural forms parsing. + } + } + + this.Translations.Add(originalStrings[0], translatedStrings); } Trace.WriteLine("String parsing completed.", "NGettext"); - return dict; - } finally { @@ -130,6 +200,14 @@ public Dictionary GetTranslations(Stream stream) } } + private void _Init() + { + this.Headers = new Dictionary(StringComparer.OrdinalIgnoreCase); + this.Translations = new Dictionary(); + this.FormatRevision = null; + this.IsBigEndian = false; + } + private string[] _ReadStrings(BinaryReader reader, int offset, int length) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); From 04c0c8ef816275992e654c9cf108dc8ea65d7ada Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 May 2015 19:32:02 +0300 Subject: [PATCH 13/55] Plural form processing refactoring. --- README.md | 10 +- src/NGettext.Tests/NGettext.Tests.csproj | 3 +- .../Plural/DefaultPluralRuleGeneratorTest.cs | 124 ++++++++ .../Plural/PluralFormProcessorTest.cs | 148 --------- src/NGettext.Tests/Plural/PluralRuleTest.cs | 37 +++ src/NGettext/BaseCatalog.cs | 61 +++- src/NGettext/NGettext.csproj | 6 +- .../Plural/DefaultPluralRuleGenerator.cs | 241 +++++++++++++++ src/NGettext/Plural/IPluralRule.cs | 22 ++ src/NGettext/Plural/IPluralRuleGenerator.cs | 18 ++ src/NGettext/Plural/PluralFormProcessor.cs | 285 ------------------ src/NGettext/Plural/PluralRule.cs | 51 ++++ .../Plural/PluralRuleEvaluatorDelegate.cs | 11 + 13 files changed, 567 insertions(+), 450 deletions(-) create mode 100644 src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs delete mode 100644 src/NGettext.Tests/Plural/PluralFormProcessorTest.cs create mode 100644 src/NGettext.Tests/Plural/PluralRuleTest.cs create mode 100644 src/NGettext/Plural/DefaultPluralRuleGenerator.cs create mode 100644 src/NGettext/Plural/IPluralRule.cs create mode 100644 src/NGettext/Plural/IPluralRuleGenerator.cs delete mode 100644 src/NGettext/Plural/PluralFormProcessor.cs create mode 100644 src/NGettext/Plural/PluralRule.cs create mode 100644 src/NGettext/Plural/PluralRuleEvaluatorDelegate.cs diff --git a/README.md b/README.md index 466f2b4..865dafe 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ NGettext [![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext) ======== -Copyright (C) 2012 Neris Ereptoris . +Copyright (C) 2012,2015 Neris Ereptoris . Just another one GNU/Gettext implementation for .NET. Requires Microsoft .NET Framework 2.0 or higher or Mono. This implementation loads translations directly from gettext *.mo files (no need to compile a satellite assembly) and can handle multiple translation domains and multiple locales in one application instance. +It supports both little-endian and big-endian MO files, automatic (header-based) encoding detection. -NGettext currently not supports *.mo file headers (stored in mo file plural formulas, encoding, etc.). -It uses precompiled plural formulas and supports custom plural formulas passed through API. -It supports both little-endian and big-endian MO files. +NGettext currently not supports loading plural form rules from *.mo file headers. +It uses precompiled plural form rules and supports custom plural form rules passed through API. @@ -159,7 +159,7 @@ Now you can use NGettext in your code: ### Custom plural formulas ```csharp - catalog.PluralForm.SetCustomFormula(cultureInfo, n => ( n == 1 ? 0 : 1 )); + catalog.PluralRule = new PluralRule(numPlurals, n => ( n == 1 ? 0 : 1 )); ``` diff --git a/src/NGettext.Tests/NGettext.Tests.csproj b/src/NGettext.Tests/NGettext.Tests.csproj index 69a58c2..5b77545 100644 --- a/src/NGettext.Tests/NGettext.Tests.csproj +++ b/src/NGettext.Tests/NGettext.Tests.csproj @@ -48,7 +48,8 @@ - + + diff --git a/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs b/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs new file mode 100644 index 0000000..967e643 --- /dev/null +++ b/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using NGettext.Plural; +using NUnit.Framework; + +namespace NGettext.Tests.Plural +{ + [TestFixture] + public class DefaultPluralRuleGeneratorTest + { + + [SetUp] + public void Init() + { + + } + + #region Default forms + + [Test] + public void TestDefaultForms() + { + var dict = new Dictionary>() + { + {"en-US", new Dictionary() + { + {0, 1}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"fa-IR", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 0}, + {3, 0}, + {5, 0}, + {10, 0}, + {999, 0}, + }}, + {"ar-SA", new Dictionary() + { + {0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {5, 3}, + {10, 3}, + {999, 5}, + }}, + {"hi", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"fr", new Dictionary() + { + {0, 0}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 1}, + {10, 1}, + {999, 1}, + }}, + {"lv", new Dictionary() + { + {0, 0}, + {1, 1}, + {2, 2}, + {3, 2}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + {"se-SE", new Dictionary() + { + {0, 2}, + {1, 0}, + {2, 1}, + {3, 2}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + {"ru-RU", new Dictionary() + { + {0, 2}, + {1, 0}, + {2, 1}, + {3, 1}, + {5, 2}, + {10, 2}, + {999, 2}, + }}, + }; + + var generator = new DefaultPluralRuleGenerator(); + foreach (var testCase in dict) + { + var locale = CultureInfo.CreateSpecificCulture(testCase.Key); + var rule = generator.CreateRule(locale); + foreach (var data in testCase.Value) + { + Assert.AreEqual(data.Value, rule.Evaluate(data.Key)); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs b/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs deleted file mode 100644 index a1b4925..0000000 --- a/src/NGettext.Tests/Plural/PluralFormProcessorTest.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; - -using NUnit.Framework; - -using NGettext.Plural; - -namespace NGettext.Tests.Plural -{ - [TestFixture] - public class PluralFormProcessorTest - { - - [SetUp] - public void Init() - { - - } - - #region Default forms - - [Test] - public void TestDefaultForms() - { - var dict = new Dictionary>() - { - {"en-US", new Dictionary() - { - {0, 1}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"fa-IR", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 0}, - {3, 0}, - {5, 0}, - {10, 0}, - {999, 0}, - }}, - {"ar-SA", new Dictionary() - { - {0, 0}, - {1, 1}, - {2, 2}, - {3, 3}, - {5, 3}, - {10, 3}, - {999, 5}, - }}, - {"hi", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"fr", new Dictionary() - { - {0, 0}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 1}, - {10, 1}, - {999, 1}, - }}, - {"lv", new Dictionary() - { - {0, 0}, - {1, 1}, - {2, 2}, - {3, 2}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - {"se-SE", new Dictionary() - { - {0, 2}, - {1, 0}, - {2, 1}, - {3, 2}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - {"ru-RU", new Dictionary() - { - {0, 2}, - {1, 0}, - {2, 1}, - {3, 1}, - {5, 2}, - {10, 2}, - {999, 2}, - }}, - }; - - - foreach (var testCase in dict) - { - var locale = CultureInfo.CreateSpecificCulture(testCase.Key); - foreach (var data in testCase.Value) - { - Assert.AreEqual(data.Value, PluralFormProcessor.Default.GetPluralFormIndex(locale, data.Key)); - } - } - } - - #endregion - - #region Custom forms - - [Test] - public void TestCustomForms() - { - var p = new PluralFormProcessor(); - - var en = CultureInfo.CreateSpecificCulture("en-US"); - p.SetCustomFormula(en, l => (int)l); - - var fr = CultureInfo.CreateSpecificCulture("fr"); - p.SetCustomFormula(fr, l => (int)(l * 2)); - - foreach (var n in new long[] { 0, 1, 2, 3, 100, 101, 102, 103 }) - { - Assert.AreEqual(n, p.GetPluralFormIndex(en, n)); - Assert.AreEqual(n * 2, p.GetPluralFormIndex(fr, n)); - } - } - - #endregion - - } -} \ No newline at end of file diff --git a/src/NGettext.Tests/Plural/PluralRuleTest.cs b/src/NGettext.Tests/Plural/PluralRuleTest.cs new file mode 100644 index 0000000..445f948 --- /dev/null +++ b/src/NGettext.Tests/Plural/PluralRuleTest.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using NGettext.Plural; +using NUnit.Framework; + +namespace NGettext.Tests.Plural +{ + [TestFixture] + public class PluralRuleTest + { + [SetUp] + public void Init() + { + + } + + #region Custom forms + + [Test] + public void TestCustomForms() + { + var rule1 = new PluralRule(1, number => (int)number); + var rule2 = new PluralRule(1, number => (int)(number * 2)); + + foreach (var n in new long[] { 0, 1, 2, 3, 100, 101, 102, 103 }) + { + Assert.AreEqual(n, rule1.Evaluate(n)); + Assert.AreEqual(n * 2, rule2.Evaluate(n)); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/src/NGettext/BaseCatalog.cs b/src/NGettext/BaseCatalog.cs index 764c4c9..fca9933 100644 --- a/src/NGettext/BaseCatalog.cs +++ b/src/NGettext/BaseCatalog.cs @@ -12,6 +12,8 @@ namespace NGettext /// public abstract class BaseCatalog : ICatalog { + private IPluralRule _PluralRule; + /// /// Context glue (<EOT> symbol) /// @@ -22,11 +24,6 @@ public abstract class BaseCatalog : ICatalog /// public CultureInfo CultureInfo { get; protected set; } - /// - /// Current plural form processor. - /// - public PluralFormProcessor PluralForms { get; protected set; } - /// /// Loaded raw translation strings. /// (msgctxt<EOT>)msgid => msgstr[] @@ -34,15 +31,51 @@ public abstract class BaseCatalog : ICatalog public Dictionary Translations { get; protected set; } /// - /// Initializes a new instance of the class that has no translations, - /// with default plural form formulas, using given culture info. + /// Gets or sets current plural form rule. + /// + public IPluralRule PluralRule + { + get { return this._PluralRule; } + set + { + if (value == null) + throw new ArgumentNullException("value"); + this._PluralRule = value; + } + } + + /// + /// Initializes a new instance of the class that has no translations + /// using given culture info with default plural form rule for given culture. /// /// Locale of this catalog. protected BaseCatalog(CultureInfo cultureInfo) + : this(cultureInfo, new DefaultPluralRuleGenerator()) + { + } + + /// + /// Initializes a new instance of the class that has no translations + /// using given culture info and given plural rule generator to generate rule for given culture. + /// + /// + /// + protected BaseCatalog(CultureInfo cultureInfo, IPluralRuleGenerator pluralRuleGenerator) + : this(cultureInfo, pluralRuleGenerator.CreateRule(cultureInfo)) + { + } + + /// + /// Initializes a new instance of the class that has no translations + /// using given culture info and given plural rule. + /// + /// + /// + protected BaseCatalog(CultureInfo cultureInfo, IPluralRule pluralRule) { - this.CultureInfo = cultureInfo; - this.PluralForms = PluralFormProcessor.Default; this.Translations = new Dictionary(); + this.CultureInfo = cultureInfo; + this.PluralRule = pluralRule; } #region ICatalog implementation @@ -184,7 +217,15 @@ public virtual string GetStringDefault(string messageId, string defaultMessage) public virtual string GetPluralStringDefault(string messageId, string defaultMessage, string defaultPluralMessage, long n) { var translations = this.GetTranslations(messageId); - var pluralIndex = this.PluralForms.GetPluralFormIndex(this.CultureInfo, n); + var pluralIndex = this.PluralRule.Evaluate(n); + if (pluralIndex < 0 || pluralIndex >= this.PluralRule.NumPlurals) + { + throw new IndexOutOfRangeException(String.Format( + "Calculated plural form index ({0}) is out of allowed range (0~{1}).", + pluralIndex, + this.PluralRule.NumPlurals - 1 + )); + } if (translations == null || translations.Length <= pluralIndex) { diff --git a/src/NGettext/NGettext.csproj b/src/NGettext/NGettext.csproj index fbbc885..0900766 100644 --- a/src/NGettext/NGettext.csproj +++ b/src/NGettext/NGettext.csproj @@ -49,7 +49,11 @@ - + + + + + diff --git a/src/NGettext/Plural/DefaultPluralRuleGenerator.cs b/src/NGettext/Plural/DefaultPluralRuleGenerator.cs new file mode 100644 index 0000000..5d6cda1 --- /dev/null +++ b/src/NGettext/Plural/DefaultPluralRuleGenerator.cs @@ -0,0 +1,241 @@ +using System; +using System.Diagnostics; +using System.Globalization; + +namespace NGettext.Plural +{ + /// + /// Default plural rule generator. + /// + public class DefaultPluralRuleGenerator : IPluralRuleGenerator + { + /// + /// Creates a plural rule for given culture. + /// + /// + /// Default furmulas created using information from http://cldr.unicode.org/ + /// + /// + /// + public virtual IPluralRule CreateRule(CultureInfo cultureInfo) + { + + var langCode = cultureInfo.TwoLetterISOLanguageName; + Trace.WriteLine(String.Format("Creating a built-in plural rule for langcode \"{0}\" for locale \"{1}\".", langCode, cultureInfo.Name), "NGettext"); + + switch (langCode) + { + case "az": + case "bm": + case "bo": + case "dz": + case "fa": + case "id": + case "ig": + case "ii": + case "hu": + case "ja": + case "jv": + case "ka": + case "kde": + case "kea": + case "km": + case "kn": + case "ko": + case "lo": + case "ms": + case "my": + case "sah": + case "ses": + case "sg": + case "th": + case "to": + case "tr": + case "vi": + case "wo": + case "yo": + case "zh": + return new PluralRule(1, number => 0); + + case "ar": + return new PluralRule(6, number => (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : (((number >= 3) && (number <= 10)) ? 3 : (((number >= 11) && (number <= 99)) ? 4 : 5))))); + + case "asa": + case "af": + case "bem": + case "bez": + case "bg": + case "bn": + case "brx": + case "ca": + case "cgg": + case "chr": + case "da": + case "de": + case "dv": + case "ee": + case "el": + case "en": + case "eo": + case "es": + case "et": + case "eu": + case "fi": + case "fo": + case "fur": + case "fy": + case "gl": + case "gsw": + case "gu": + case "ha": + case "haw": + case "he": + case "is": + case "it": + case "jmc": + case "kaj": + case "kcg": + case "kk": + case "kl": + case "ksb": + case "ku": + case "lb": + case "lg": + case "mas": + case "ml": + case "mn": + case "mr": + case "nah": + case "nb": + case "nd": + case "ne": + case "nl": + case "nn": + case "no": + case "nr": + case "ny": + case "nyn": + case "om": + case "or": + case "pa": + case "pap": + case "ps": + case "pt": + case "rof": + case "rm": + case "rwk": + case "saq": + case "seh": + case "sn": + case "so": + case "sq": + case "ss": + case "ssy": + case "st": + case "sv": + case "sw": + case "syr": + case "ta": + case "te": + case "teo": + case "tig": + case "tk": + case "tn": + case "ts": + case "ur": + case "wae": + case "ve": + case "vun": + case "xh": + case "xog": + case "zu": + return new PluralRule(2, number => (number == 1) ? 0 : 1); + + case "ak": + case "am": + case "bh": + case "fil": + case "ff": + case "fr": + case "guw": + case "hi": + case "kab": + case "ln": + case "mg": + case "nso": + case "ti": + case "wa": + return new PluralRule(2, number => ((number == 0) || (number == 1)) ? 0 : 1); + + case "lv": + return new PluralRule(3, number => (number == 0) ? 0 : (((number % 10 == 1) && (number % 100 != 11)) ? 1 : 2)); + + case "iu": + case "kw": + case "naq": + case "se": + case "sma": + case "smi": + case "smj": + case "smn": + case "sms": + return new PluralRule(3, number => (number == 1) ? 0 : ((number == 2) ? 1 : 2)); + + case "ga": + return new PluralRule(5, number => (number == 1) ? 0 : ((number == 2) ? 1 : (((number >= 3) && (number <= 6)) ? 2 : ((number >= 7 && number <= 10) ? 3 : 4)))); + + case "ro": + case "mo": + return new PluralRule(3, number => (number == 1) ? 0 : (((number == 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2)); + + case "lt": + return new PluralRule(3, number => ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2)); + + case "be": + case "bs": + case "hr": + case "ru": + case "sh": + case "sr": + case "uk": + return new PluralRule(3, number => ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2)); + + case "cs": + case "sk": + return new PluralRule(3, number => (number == 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2)); + + case "pl": + return new PluralRule(3, number => (number == 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2)); + + case "sl": + return new PluralRule(4, number => (number % 100 == 1) ? 0 : ((number % 100 == 2) ? 1 : (((number % 100 == 3) || (number % 100 == 4)) ? 2 : 3))); + + case "mt": + return new PluralRule(4, number => (number == 1) ? 0 : (((number == 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3))); + + case "mk": + return new PluralRule(2, number => ((number % 10 == 1) && (number != 11)) ? 0 : 1); + + case "cy": + return new PluralRule(6, number => (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : ((number == 3) ? 3 : ((number == 6) ? 4 : 5))))); + + case "lag": + case "ksh": + return new PluralRule(3, number => (number == 0) ? 0 : ((number == 1) ? 1 : 2)); + + case "shi": + return new PluralRule(3, number => ((number == 0) && (number == 1)) ? 0 : (((number >= 2) && (number <= 10)) ? 1 : 2)); + + case "tzm": + return new PluralRule(2, number => ((number == 0) || (number == 1) || (((number >= 11) && (number <= 99)))) ? 0 : 1); + + case "gv": + return new PluralRule(2, number => ((number % 10 == 1) || (number % 10 == 2) || (number % 20 == 0)) ? 0 : 1); + + case "gd": + return new PluralRule(4, number => ((number == 1) || (number == 11)) ? 0 : (((number == 2) || (number == 12)) ? 1 : (((((number >= 3) && (number <= 10)) || ((number >= 13) && (number <= 19))) ? 2 : 3)))); + } + return new PluralRule(1, number => 0); + } + } +} \ No newline at end of file diff --git a/src/NGettext/Plural/IPluralRule.cs b/src/NGettext/Plural/IPluralRule.cs new file mode 100644 index 0000000..0b89f08 --- /dev/null +++ b/src/NGettext/Plural/IPluralRule.cs @@ -0,0 +1,22 @@ +using System; + +namespace NGettext.Plural +{ + /// + /// Represents a plural form rule whitch can generate a plural form index by given number. + /// + public interface IPluralRule + { + /// + /// Maximum number of plural forms supported. + /// + int NumPlurals { get; } + + /// + /// Evaluates a number and returns a plural form index. + /// + /// Number whitch needs to be evaluated. + /// Plural form index. + int Evaluate(long number); + } +} \ No newline at end of file diff --git a/src/NGettext/Plural/IPluralRuleGenerator.cs b/src/NGettext/Plural/IPluralRuleGenerator.cs new file mode 100644 index 0000000..95f489c --- /dev/null +++ b/src/NGettext/Plural/IPluralRuleGenerator.cs @@ -0,0 +1,18 @@ +using System; +using System.Globalization; + +namespace NGettext.Plural +{ + /// + /// Plural rule generator. + /// + public interface IPluralRuleGenerator + { + /// + /// Creates a plural rule for given culture. + /// + /// + /// + IPluralRule CreateRule(CultureInfo cultureInfo); + } +} \ No newline at end of file diff --git a/src/NGettext/Plural/PluralFormProcessor.cs b/src/NGettext/Plural/PluralFormProcessor.cs deleted file mode 100644 index afb1936..0000000 --- a/src/NGettext/Plural/PluralFormProcessor.cs +++ /dev/null @@ -1,285 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; - -namespace NGettext.Plural -{ - /// - /// Plural forms processor. - /// - public class PluralFormProcessor - { - /// - /// Returns plural form index by given number. - /// - /// - /// - public delegate int FormulaDelegate(long n); - - /// - /// Default plural forms processor. - /// - public static readonly PluralFormProcessor Default = new PluralFormProcessor(); - - /// - /// Collection with custom plural forms formulas. - /// Culture Info LCID => Formula function - /// - private readonly Dictionary _CustomFormulas = new Dictionary(); - - /// - /// Set custom plural form formula function for given locale. - /// - /// Locale - /// Function that returns plural form index by given number. - public void SetCustomFormula(CultureInfo cultureInfo, FormulaDelegate formula) - { - this._CustomFormulas.Add(cultureInfo.LCID, formula); - } - - /// - /// Get plural form index for given locale by given number. - /// - /// - /// Default furmulas created using information from http://cldr.unicode.org/ - /// - /// - /// - /// - public int GetPluralFormIndex(CultureInfo cultureInfo, long number) - { - Trace.WriteLine(String.Format("Getting plural index for locale \"{0}\" and number \"{1}\".", cultureInfo.Name, number), "NGettext"); - - if (this._CustomFormulas.ContainsKey(cultureInfo.LCID)) - { - var formula = this._CustomFormulas[cultureInfo.LCID]; - if (formula != null) - { - Trace.WriteLine(String.Format("Using custom plural formula for locale \"{0}\".", cultureInfo.Name), "NGettext"); - return formula.Invoke(number); - } - } - - var langCode = cultureInfo.TwoLetterISOLanguageName; - Trace.WriteLine(String.Format("Using built-in plural formula with langcode \"{0}\" for locale \"{1}\".", langCode, cultureInfo.Name), "NGettext"); - - - switch (langCode) - { - case "az": - case "bm": - case "bo": - case "dz": - case "fa": - case "id": - case "ig": - case "ii": - case "hu": - case "ja": - case "jv": - case "ka": - case "kde": - case "kea": - case "km": - case "kn": - case "ko": - case "lo": - case "ms": - case "my": - case "sah": - case "ses": - case "sg": - case "th": - case "to": - case "tr": - case "vi": - case "wo": - case "yo": - case "zh": - return 0; - - case "ar": - return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : (((number >= 3) && (number <= 10)) ? 3 : (((number >= 11) && (number <= 99)) ? 4 : 5)))); - - case "asa": - case "af": - case "bem": - case "bez": - case "bg": - case "bn": - case "brx": - case "ca": - case "cgg": - case "chr": - case "da": - case "de": - case "dv": - case "ee": - case "el": - case "en": - case "eo": - case "es": - case "et": - case "eu": - case "fi": - case "fo": - case "fur": - case "fy": - case "gl": - case "gsw": - case "gu": - case "ha": - case "haw": - case "he": - case "is": - case "it": - case "jmc": - case "kaj": - case "kcg": - case "kk": - case "kl": - case "ksb": - case "ku": - case "lb": - case "lg": - case "mas": - case "ml": - case "mn": - case "mr": - case "nah": - case "nb": - case "nd": - case "ne": - case "nl": - case "nn": - case "no": - case "nr": - case "ny": - case "nyn": - case "om": - case "or": - case "pa": - case "pap": - case "ps": - case "pt": - case "rof": - case "rm": - case "rwk": - case "saq": - case "seh": - case "sn": - case "so": - case "sq": - case "ss": - case "ssy": - case "st": - case "sv": - case "sw": - case "syr": - case "ta": - case "te": - case "teo": - case "tig": - case "tk": - case "tn": - case "ts": - case "ur": - case "wae": - case "ve": - case "vun": - case "xh": - case "xog": - case "zu": - return (number == 1) ? 0 : 1; - - case "ak": - case "am": - case "bh": - case "fil": - case "ff": - case "fr": - case "guw": - case "hi": - case "kab": - case "ln": - case "mg": - case "nso": - case "ti": - case "wa": - return ((number == 0) || (number == 1)) ? 0 : 1; - - case "lv": - return (number == 0) ? 0 : (((number % 10 == 1) && (number % 100 != 11)) ? 1 : 2); - - case "iu": - case "kw": - case "naq": - case "se": - case "sma": - case "smi": - case "smj": - case "smn": - case "sms": - return (number == 1) ? 0 : ((number == 2) ? 1 : 2); - - case "ga": - return (number == 1) ? 0 : ((number == 2) ? 1 : (((number >= 3) && (number <= 6)) ? 2 : ((number >= 7 && number <= 10) ? 3 : 4))); - - case "ro": - case "mo": - return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2); - - case "lt": - return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); - - case "be": - case "bs": - case "hr": - case "ru": - case "sh": - case "sr": - case "uk": - return ((number % 10 == 1) && (number % 100 != 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2); - - case "cs": - case "sk": - return (number == 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2); - - case "pl": - return (number == 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2); - - case "sl": - return (number % 100 == 1) ? 0 : ((number % 100 == 2) ? 1 : (((number % 100 == 3) || (number % 100 == 4)) ? 2 : 3)); - - case "mt": - return (number == 1) ? 0 : (((number == 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3)); - - case "mk": - return ((number % 10 == 1) && (number != 11)) ? 0 : 1; - - case "cy": - return (number == 0) ? 0 : ((number == 1) ? 1 : ((number == 2) ? 2 : ((number == 3) ? 3 : ((number == 6) ? 4 : 5)))); - - case "lag": - case "ksh": - return (number == 0) ? 0 : ((number == 1) ? 1 : 2); - - case "shi": - return ((number == 0) && (number == 1)) ? 0 : (((number >= 2) && (number <= 10)) ? 1 : 2); - - case "tzm": - return ((number == 0) || (number == 1) || (((number >= 11) && (number <= 99)))) ? 0 : 1; - - case "gv": - return ((number % 10 == 1) || (number % 10 == 2) || (number % 20 == 0)) ? 0 : 1; - - case "gd": - return ((number == 1) || (number == 11)) ? 0 : (((number == 2) || (number == 12)) ? 1 : (((((number >= 3) && (number <= 10)) || ((number >= 13) && (number <= 19))) ? 2 : 3))); - - default: - return 0; - } - } - } -} \ No newline at end of file diff --git a/src/NGettext/Plural/PluralRule.cs b/src/NGettext/Plural/PluralRule.cs new file mode 100644 index 0000000..ca6ce9c --- /dev/null +++ b/src/NGettext/Plural/PluralRule.cs @@ -0,0 +1,51 @@ +using System; + +namespace NGettext.Plural +{ + /// + /// Default plural rule implementation whitch uses a evaluation delegate instance to evaluate a plural form. + /// + public class PluralRule : IPluralRule + { + /// + /// Evaluation delegate instance. + /// + protected PluralRuleEvaluatorDelegate EvaluatorDelegate; + + /// + /// Maximum number of plural forms supported. + /// + public int NumPlurals { get; protected set; } + + /// + /// Initializes a new instance of the class using specified maximum plural + /// forms value and an evaluation delegate. + /// + /// + /// + public PluralRule(int numPlurals, PluralRuleEvaluatorDelegate evaluatorDelegate) + { + if (numPlurals <= 0) + { + throw new ArgumentOutOfRangeException("numPlurals"); + } + if (evaluatorDelegate == null) + { + throw new ArgumentNullException("evaluatorDelegate"); + } + + this.NumPlurals = numPlurals; + this.EvaluatorDelegate = evaluatorDelegate; + } + + /// + /// Evaluates a number and returns a plural form index. + /// + /// Number whitch needs to be evaluated. + /// Plural form index. + public virtual int Evaluate(long number) + { + return this.EvaluatorDelegate.Invoke(number); + } + } +} \ No newline at end of file diff --git a/src/NGettext/Plural/PluralRuleEvaluatorDelegate.cs b/src/NGettext/Plural/PluralRuleEvaluatorDelegate.cs new file mode 100644 index 0000000..96df9d9 --- /dev/null +++ b/src/NGettext/Plural/PluralRuleEvaluatorDelegate.cs @@ -0,0 +1,11 @@ +using System; + +namespace NGettext.Plural +{ + /// + /// Represents a plural rule evaluation delegate used in the DefaultPluralRule. + /// + /// Number whitch needs to be evaluated. + /// Plural form index. + public delegate int PluralRuleEvaluatorDelegate(long number); +} \ No newline at end of file From 6f07305ab5c273a76fb24cddd4fd5dc40119d9a2 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 18 Jun 2015 23:42:20 +0300 Subject: [PATCH 14/55] Refactorings to be able to implement different catalog loader. --- src/NGettext.Tests/BaseCatalogTest.cs | 16 +- .../Loaders/MoFileParserTest.cs | 4 +- src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs | 2 +- src/NGettext/BaseCatalog.cs | 252 ------------- src/NGettext/Catalog.cs | 355 ++++++++++++------ src/NGettext/Loaders/ILoader.cs | 16 + src/NGettext/Loaders/MoAstPluralLoader.cs | 39 ++ src/NGettext/Loaders/MoFileParser.cs | 4 - src/NGettext/Loaders/MoLoader.cs | 206 ++++++++++ src/NGettext/NGettext.csproj | 8 +- src/NGettext/Plural/AstPluralRuleGenerator.cs | 58 +++ src/NGettext/Plural/IPluralRuleTextParser.cs | 16 + src/NGettext/Plural/PluralRule.cs | 3 + 13 files changed, 601 insertions(+), 378 deletions(-) delete mode 100644 src/NGettext/BaseCatalog.cs create mode 100644 src/NGettext/Loaders/ILoader.cs create mode 100644 src/NGettext/Loaders/MoAstPluralLoader.cs create mode 100644 src/NGettext/Loaders/MoLoader.cs create mode 100644 src/NGettext/Plural/AstPluralRuleGenerator.cs create mode 100644 src/NGettext/Plural/IPluralRuleTextParser.cs diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index 84f708c..faaba00 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -24,7 +24,7 @@ public void Init() [Test] public void TestGetString() { - var t = new EmptyBaseCatalog(); + var t = new Catalog(); t.Translations.Add("key1", new[] { "value1" }); t.Translations.Add("key2", new[] { "value2" }); t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); @@ -40,7 +40,7 @@ public void TestGetString() [Test] public void TestGetStringFormat() { - var t = new EmptyBaseCatalog(); + var t = new Catalog(); Assert.AreEqual("Foo bar", t.GetString("Foo {0}", "bar")); Assert.AreEqual("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); @@ -50,8 +50,8 @@ public void TestGetStringFormat() [Test] public void TestGetStringFormatCulture() { - var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); - var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); + var catalogEn = new Catalog(new CultureInfo("en-US")); + var catalogRu = new Catalog(new CultureInfo("ru-RU")); Assert.AreEqual("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); Assert.AreEqual("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); @@ -127,8 +127,8 @@ public void TestGetParticularString() { var t = new EmptyBaseCatalog(); t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value3" }); + t.Translations.Add("context1" + Catalog.CONTEXT_GLUE + "key1", new[] { "value2" }); + t.Translations.Add("context2" + Catalog.CONTEXT_GLUE + "key1", new[] { "value3" }); Assert.AreEqual("value1", t.GetString("key1")); Assert.AreEqual("value2", t.GetParticularString("context1", "key1")); @@ -163,8 +163,8 @@ public void TestGetParticularStringFormatCulture() public void TestGetParticularPluralString() { var t = new EmptyBaseCatalog(CultureInfo.CreateSpecificCulture("en-US")); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); + t.Translations.Add("context1" + Catalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); + t.Translations.Add("context2" + Catalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); Assert.AreEqual("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); Assert.AreEqual("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index bc251e8..70504af 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -71,8 +71,8 @@ private void _TestLoadedTranslation(IDictionary dict) Assert.AreEqual(new[] { "тест" }, dict["test"]); Assert.AreEqual(new[] { "тест2" }, dict["test2"]); Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + Catalog.CONTEXT_GLUE + "test3"]); + Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + Catalog.CONTEXT_GLUE + "test3"]); } } } \ No newline at end of file diff --git a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs index 0927121..4cd95b4 100644 --- a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs +++ b/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs @@ -6,7 +6,7 @@ namespace NGettext.Tests.Stabs { - public class EmptyBaseCatalog : BaseCatalog + public class EmptyBaseCatalog : Catalog { public EmptyBaseCatalog() : base(CultureInfo.CurrentUICulture) { } diff --git a/src/NGettext/BaseCatalog.cs b/src/NGettext/BaseCatalog.cs deleted file mode 100644 index fca9933..0000000 --- a/src/NGettext/BaseCatalog.cs +++ /dev/null @@ -1,252 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; - -using NGettext.Plural; - -namespace NGettext -{ - /// - /// Base catalog. - /// - public abstract class BaseCatalog : ICatalog - { - private IPluralRule _PluralRule; - - /// - /// Context glue (<EOT> symbol) - /// - public const char CONTEXT_GLUE = '\u0004'; - - /// - /// Current catalog locale. - /// - public CultureInfo CultureInfo { get; protected set; } - - /// - /// Loaded raw translation strings. - /// (msgctxt<EOT>)msgid => msgstr[] - /// - public Dictionary Translations { get; protected set; } - - /// - /// Gets or sets current plural form rule. - /// - public IPluralRule PluralRule - { - get { return this._PluralRule; } - set - { - if (value == null) - throw new ArgumentNullException("value"); - this._PluralRule = value; - } - } - - /// - /// Initializes a new instance of the class that has no translations - /// using given culture info with default plural form rule for given culture. - /// - /// Locale of this catalog. - protected BaseCatalog(CultureInfo cultureInfo) - : this(cultureInfo, new DefaultPluralRuleGenerator()) - { - } - - /// - /// Initializes a new instance of the class that has no translations - /// using given culture info and given plural rule generator to generate rule for given culture. - /// - /// - /// - protected BaseCatalog(CultureInfo cultureInfo, IPluralRuleGenerator pluralRuleGenerator) - : this(cultureInfo, pluralRuleGenerator.CreateRule(cultureInfo)) - { - } - - /// - /// Initializes a new instance of the class that has no translations - /// using given culture info and given plural rule. - /// - /// - /// - protected BaseCatalog(CultureInfo cultureInfo, IPluralRule pluralRule) - { - this.Translations = new Dictionary(); - this.CultureInfo = cultureInfo; - this.PluralRule = pluralRule; - } - - #region ICatalog implementation - - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Translated text. - public virtual string GetString(string text) - { - return this.GetStringDefault(text, text); - } - - /// - /// Returns translated into the selected language. - /// Similar to gettext function. - /// - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - public virtual string GetString(string text, params object[] args) - { - return String.Format(this.CultureInfo, this.GetStringDefault(text, text), args); - } - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - public virtual string GetPluralString(string text, string pluralText, long n) - { - return this.GetPluralStringDefault(text, text, pluralText, n); - } - - /// - /// Returns the plural form for of the translation of . - /// Similar to ngettext function. - /// - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - public virtual string GetPluralString(string text, string pluralText, long n, params object[] args) - { - return String.Format(this.CultureInfo, this.GetPluralStringDefault(text, text, pluralText, n), args); - } - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Translated text. - public virtual string GetParticularString(string context, string text) - { - return this.GetStringDefault(context + CONTEXT_GLUE + text, text); - } - - /// - /// Returns translated into the selected language using given . - /// Similar to pgettext function. - /// - /// Context. - /// Text to translate. - /// Optional arguments for method. - /// Translated text. - public virtual string GetParticularString(string context, string text, params object[] args) - { - return String.Format(this.CultureInfo, this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); - } - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Translated text. - public virtual string GetParticularPluralString(string context, string text, string pluralText, long n) - { - return this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n); - } - - /// - /// Returns the plural form for of the translation of using given . - /// Similar to npgettext function. - /// - /// Context. - /// Singular form of message to translate. - /// Plural form of message to translate. - /// Value that determines the plural form. - /// Optional arguments for method. - /// Translated text. - public virtual string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args) - { - return String.Format(this.CultureInfo, this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); - } - - #endregion - - /// - /// Returns translated string for given or on fail. - /// - /// Message ID - /// Default message - /// Translated string - public virtual string GetStringDefault(string messageId, string defaultMessage) - { - var translations = this.GetTranslations(messageId); - - if (translations == null || translations.Length == 0) - { - Trace.WriteLine(String.Format("Translation not found for message id \"{0}\".", messageId), "NGettext"); - return defaultMessage; - } - - return translations[0]; - } - - /// - /// Returns translated plural string for given or - /// or on fail. - /// - /// Message ID - /// Default message singular form - /// Default message plural form - /// Value that determines the plural form - /// Translated string - public virtual string GetPluralStringDefault(string messageId, string defaultMessage, string defaultPluralMessage, long n) - { - var translations = this.GetTranslations(messageId); - var pluralIndex = this.PluralRule.Evaluate(n); - if (pluralIndex < 0 || pluralIndex >= this.PluralRule.NumPlurals) - { - throw new IndexOutOfRangeException(String.Format( - "Calculated plural form index ({0}) is out of allowed range (0~{1}).", - pluralIndex, - this.PluralRule.NumPlurals - 1 - )); - } - - if (translations == null || translations.Length <= pluralIndex) - { - Trace.WriteLine(String.Format("Translation not found (plural) for message id \"{0}\".", messageId), "NGettext"); - return (n == 1) ? defaultMessage : defaultPluralMessage; - } - - return translations[pluralIndex]; - } - - /// - /// Returns all translations for given . - /// - /// - /// Returns all translations for given or null if not found. - public virtual string[] GetTranslations(string messageId) - { - if (String.IsNullOrEmpty(messageId)) return null; - if (!this.Translations.ContainsKey(messageId)) return null; - - return this.Translations[messageId]; - } - } -} \ No newline at end of file diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index 2447a7f..c669b3d 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -1,193 +1,330 @@ using System; +using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Globalization; -using System.Text; - +using System.IO; using NGettext.Loaders; +using NGettext.Plural; namespace NGettext { /// /// Represents a Gettext catalog instance. - /// Loads translations from gettext *.mo files. /// - public class Catalog : BaseCatalog + public class Catalog : ICatalog { + private IPluralRule _PluralRule; + + /// + /// Context glue (<EOT> symbol) + /// + public const char CONTEXT_GLUE = '\u0004'; + /// - /// Initializes a new instance of the class with no translations and with current CultureInfo. + /// Current catalog locale. + /// + public CultureInfo CultureInfo { get; protected set; } + + /// + /// Loaded raw translation strings. + /// (msgctxt<EOT>)msgid => msgstr[] + /// + public Dictionary Translations { get; protected set; } + + /// + /// Gets or sets current plural form rule. + /// + public IPluralRule PluralRule + { + get { return this._PluralRule; } + set + { + if (value == null) + throw new ArgumentNullException("value"); + this._PluralRule = value; + } + } + + #region Constructors + + /// + /// Initializes a new instance of the class that has no translations + /// using the current UI culture info and default plural rule. /// public Catalog() - : base(CultureInfo.CurrentUICulture) + : this(CultureInfo.CurrentUICulture) { - } /// - /// Initializes a new instance of the class with no translations and with given CultureInfo. + /// Initializes a new instance of the class that has no translations + /// using given culture info and default plural rule. /// - /// Culture info + /// Culture info. public Catalog(CultureInfo cultureInfo) - : base(cultureInfo) { - + this.CultureInfo = cultureInfo; + this.Translations = new Dictionary(); + this.PluralRule = Plural.PluralRule.Default; } /// - /// Initializes a new instance of the class with current CultureInfo - /// and loads MO translations from given stream. + /// Initializes a new instance of the class using the current UI culture info + /// and loads data using given loader. /// - /// Stream that contain binary data in the MO file format - public Catalog(Stream moStream) - : this() + /// Loader instance. + public Catalog(ILoader loader) + : this(loader, CultureInfo.CurrentUICulture) { - try - { - this.Load(moStream); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } } /// - /// Initializes a new instance of the class with given CultureInfo - /// and loads MO translations from given stream. + /// Initializes a new instance of the class using given culture info + /// and loads data using given loader. /// - /// Stream that contain binary data in the MO file format - /// Culture info - public Catalog(Stream moStream, CultureInfo cultureInfo) + /// Loader instance. + /// Culture info. + public Catalog(ILoader loader, CultureInfo cultureInfo) : this(cultureInfo) { try { - this.Load(moStream); + this.Load(loader); } catch (FileNotFoundException exception) { + // Supress FileNotFound exceptions Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); } } /// - /// Initializes a new instance of the class with current CultureInfo - /// and loads translations from MO file that can be found by given parameters. + /// Initializes a new instance of the class using the current UI culture info + /// and loads data from specified stream using a new instance. + /// + /// Stream that contain binary data in the MO file format. + public Catalog(Stream moStream) + : this(new MoLoader(moStream)) + { + } + + /// + /// Initializes a new instance of the class using given culture info + /// and loads data from specified stream using a new instance. /// - /// Catalog domain name - /// Directory that contains gettext localization files + /// Stream that contain binary data in the MO file format. + /// Culture info. + public Catalog(Stream moStream, CultureInfo cultureInfo) + : this(new MoLoader(moStream), cultureInfo) + { + } + + /// + /// Initializes a new instance of the class using the current UI culture info + /// and loads data for specified domain and locale directory using a new instance. + /// + /// Catalog domain name. + /// Directory that contains gettext localization files. public Catalog(string domain, string localeDir) - : this() + : this(new MoLoader(domain, localeDir)) { - try - { - this.Load(this.CultureInfo, domain, localeDir); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } } /// - /// Initializes a new instance of the class with given CultureInfo - /// and loads translations from MO file that can be found by given parameters. + /// Initializes a new instance of the class using given culture info + /// and loads data for specified domain and locale directory using a new instance. /// - /// Catalog domain name - /// Directory that contains gettext localization files - /// Culture info + /// Catalog domain name. + /// Directory that contains gettext localization files. + /// Culture info. public Catalog(string domain, string localeDir, CultureInfo cultureInfo) - : this(cultureInfo) + : this(new MoLoader(domain, localeDir), cultureInfo) { - try - { - this.Load(this.CultureInfo, domain, localeDir); - } - catch (FileNotFoundException exception) - { - Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); - } } + #endregion + /// - /// Load translations from MO file that can be found by given parameters. + /// Loads data to the current catalog using specified loader instance. /// - /// Culture info - /// Catalog domain name - /// Directory that contains gettext localization files - public void Load(CultureInfo cultureInfo, string domain, string localeDir) + /// Loader instance. + public void Load(ILoader loader) { - var path = this._FindTranslationFile(cultureInfo, domain, localeDir); - if (path == null) - { - throw new FileNotFoundException(String.Format("Can not find MO file name in locale directory \"{0}\".", localeDir)); - } + if (loader == null) + throw new ArgumentNullException("loader"); + + loader.Load(this); + } + + #region ICatalog implementation - this.Load(path); + /// + /// Returns translated into the selected language. + /// Similar to gettext function. + /// + /// Text to translate. + /// Translated text. + public virtual string GetString(string text) + { + return this.GetStringDefault(text, text); } /// - /// Load translations from MO file that can be found by given path. + /// Returns translated into the selected language. + /// Similar to gettext function. /// - /// Path to *.mo file - public void Load(string path) + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + public virtual string GetString(string text, params object[] args) { - Trace.WriteLine(String.Format("Loading translations from file \"{0}\"...", path), "NGettext"); - using (var stream = File.OpenRead(path)) - { - this.Load(stream); - } + return String.Format(this.CultureInfo, this.GetStringDefault(text, text), args); } /// - /// Load translations from given MO file stream using given encoding. + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. /// - /// - /// By default, parser will try to detect file encoding automatically with fallback to UTF-8 encoding. - /// If you specify any encoding in this method, auto-detect will be turned off and given encoding will be used instead. - /// - /// Stream that contain binary data in the MO file format - /// File encoding (auto detect by default) - public void Load(Stream moStream, Encoding encoding = null) + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + public virtual string GetPluralString(string text, string pluralText, long n) { - var parser = new MoFileParser(); - if (encoding != null) + return this.GetPluralStringDefault(text, text, pluralText, n); + } + + /// + /// Returns the plural form for of the translation of . + /// Similar to ngettext function. + /// + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + public virtual string GetPluralString(string text, string pluralText, long n, params object[] args) + { + return String.Format(this.CultureInfo, this.GetPluralStringDefault(text, text, pluralText, n), args); + } + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Translated text. + public virtual string GetParticularString(string context, string text) + { + return this.GetStringDefault(context + CONTEXT_GLUE + text, text); + } + + /// + /// Returns translated into the selected language using given . + /// Similar to pgettext function. + /// + /// Context. + /// Text to translate. + /// Optional arguments for method. + /// Translated text. + public virtual string GetParticularString(string context, string text, params object[] args) + { + return String.Format(this.CultureInfo, this.GetStringDefault(context + CONTEXT_GLUE + text, text), args); + } + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Translated text. + public virtual string GetParticularPluralString(string context, string text, string pluralText, long n) + { + return this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n); + } + + /// + /// Returns the plural form for of the translation of using given . + /// Similar to npgettext function. + /// + /// Context. + /// Singular form of message to translate. + /// Plural form of message to translate. + /// Value that determines the plural form. + /// Optional arguments for method. + /// Translated text. + public virtual string GetParticularPluralString(string context, string text, string pluralText, long n, params object[] args) + { + return String.Format(this.CultureInfo, this.GetPluralStringDefault(context + CONTEXT_GLUE + text, text, pluralText, n), args); + } + + #endregion + + /// + /// Returns translated string for given or on fail. + /// + /// Message ID + /// Default message + /// Translated string + public virtual string GetStringDefault(string messageId, string defaultMessage) + { + var translations = this.GetTranslations(messageId); + + if (translations == null || translations.Length == 0) { - parser.DetectEncoding = false; - parser.Encoding = encoding; + Trace.WriteLine(String.Format("Translation not found for message id \"{0}\".", messageId), "NGettext"); + return defaultMessage; } - parser.Parse(moStream); - - this.Translations = parser.Translations; + return translations[0]; } - private string _FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) + /// + /// Returns translated plural string for given or + /// or on fail. + /// + /// Message ID + /// Default message singular form + /// Default message plural form + /// Value that determines the plural form + /// Translated string + public virtual string GetPluralStringDefault(string messageId, string defaultMessage, string defaultPluralMessage, long n) { - var possibleFiles = new [] { - this._GetFileName(localeDir, domain, cultureInfo.Name), - this._GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) - }; + var translations = this.GetTranslations(messageId); + var pluralIndex = this.PluralRule.Evaluate(n); + if (pluralIndex < 0 || pluralIndex >= this.PluralRule.NumPlurals) + { + throw new IndexOutOfRangeException(String.Format( + "Calculated plural form index ({0}) is out of allowed range (0~{1}).", + pluralIndex, + this.PluralRule.NumPlurals - 1 + )); + } - foreach (var possibleFilePath in possibleFiles) + if (translations == null || translations.Length <= pluralIndex) { - if (File.Exists(possibleFilePath)) - { - return possibleFilePath; - } + Trace.WriteLine(String.Format("Translation not found (plural) for message id \"{0}\".", messageId), "NGettext"); + return (n == 1) ? defaultMessage : defaultPluralMessage; } - return null; + return translations[pluralIndex]; } - private string _GetFileName(string localeDir, string domain, string locale) + /// + /// Returns all translations for given . + /// + /// + /// Returns all translations for given or null if not found. + public virtual string[] GetTranslations(string messageId) { - var relativePath = - locale.Replace('-', '_') + Path.DirectorySeparatorChar + - "LC_MESSAGES" + Path.DirectorySeparatorChar + - domain + ".mo"; + if (String.IsNullOrEmpty(messageId)) return null; + if (!this.Translations.ContainsKey(messageId)) return null; - return Path.Combine(localeDir, relativePath); + return this.Translations[messageId]; } } } \ No newline at end of file diff --git a/src/NGettext/Loaders/ILoader.cs b/src/NGettext/Loaders/ILoader.cs new file mode 100644 index 0000000..cce3deb --- /dev/null +++ b/src/NGettext/Loaders/ILoader.cs @@ -0,0 +1,16 @@ +using System; + +namespace NGettext.Loaders +{ + /// + /// Represents an abstract loader that loads required data to the catalog. + /// + public interface ILoader + { + /// + /// Loads translations to the specified catalog using catalog's culture info. + /// + /// A catalog instance to load translations to. + void Load(Catalog catalog); + } +} \ No newline at end of file diff --git a/src/NGettext/Loaders/MoAstPluralLoader.cs b/src/NGettext/Loaders/MoAstPluralLoader.cs new file mode 100644 index 0000000..b6629c6 --- /dev/null +++ b/src/NGettext/Loaders/MoAstPluralLoader.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using NGettext.Plural; + +namespace NGettext.Loaders +{ + public class MoAstPluralLoader : MoLoader + { + public MoAstPluralLoader(string domain, string localeDir, MoFileParser parser) + : base(domain, localeDir, new AstPluralRuleGenerator(), parser) + { + } + + public MoAstPluralLoader(string filePath, MoFileParser parser) + : base(filePath, new AstPluralRuleGenerator(), parser) + { + } + + public MoAstPluralLoader(Stream moStream, MoFileParser parser) + : base(moStream, new AstPluralRuleGenerator(), parser) + { + } + + public MoAstPluralLoader(string domain, string localeDir) + : base(domain, localeDir, new AstPluralRuleGenerator(), new MoFileParser()) + { + } + + public MoAstPluralLoader(string filePath) + : base(filePath, new AstPluralRuleGenerator(), new MoFileParser()) + { + } + + public MoAstPluralLoader(Stream moStream) + : base(moStream, new AstPluralRuleGenerator(), new MoFileParser()) + { + } + } +} \ No newline at end of file diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index d328485..3c9cc8e 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -182,10 +182,6 @@ public void Parse(Stream stream) Trace.WriteLine(String.Format("Unable to change parser encoding using the Content-Type header: \"{0}\".", exception.Message), "NGettext"); } } - if (this.Headers.ContainsKey("Plural-Forms")) - { - //TODO: Plural forms parsing. - } } this.Translations.Add(originalStrings[0], translatedStrings); diff --git a/src/NGettext/Loaders/MoLoader.cs b/src/NGettext/Loaders/MoLoader.cs new file mode 100644 index 0000000..f869c92 --- /dev/null +++ b/src/NGettext/Loaders/MoLoader.cs @@ -0,0 +1,206 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using NGettext.Plural; + +namespace NGettext.Loaders +{ + /// + /// A catalog loader that loads data from files in the GNU/Gettext MO file format. + /// + public class MoLoader : ILoader + { + private readonly Stream _MoStream; + private readonly string _FilePath; + private readonly string _Domain; + private readonly string _LocaleDir; + + /// + /// Gets a current plural generator instance. + /// + public IPluralRuleGenerator PluralRuleGenerator { get; private set; } + + /// + /// Gets a MO file format parser instance. + /// + public MoFileParser Parser { get; private set; } + + /// + /// Initializes a new instance of the class whitch will try to load a MO file + /// that will be located in the localeDir using the domain name and catalog's culture info. + /// + /// + /// + /// + /// + public MoLoader(string domain, string localeDir, IPluralRuleGenerator pluralRuleGenerator, MoFileParser parser) + { + if (domain == null) + throw new ArgumentNullException("domain"); + if (localeDir == null) + throw new ArgumentNullException("localeDir"); + if (pluralRuleGenerator == null) + throw new ArgumentNullException("pluralRuleGenerator"); + if (parser == null) + throw new ArgumentNullException("parser"); + + this._Domain = domain; + this._LocaleDir = localeDir; + this.PluralRuleGenerator = pluralRuleGenerator; + this.Parser = parser; + } + + /// + /// Initializes a new instance of the class whitch will try to load a MO file + /// from the specified path. + /// + /// + /// + /// + public MoLoader(string filePath, IPluralRuleGenerator pluralRuleGenerator, MoFileParser parser) + { + if (filePath == null) + throw new ArgumentNullException("filePath"); + if (pluralRuleGenerator == null) + throw new ArgumentNullException("pluralRuleGenerator"); + if (parser == null) + throw new ArgumentNullException("parser"); + + this._FilePath = filePath; + this.PluralRuleGenerator = pluralRuleGenerator; + this.Parser = parser; + } + + /// + /// Initializes a new instance of the class whitch will try to load a MO file + /// from the specified stream. + /// + /// + /// + /// + public MoLoader(Stream moStream, IPluralRuleGenerator pluralRuleGenerator, MoFileParser parser) + { + if (moStream == null) + throw new ArgumentNullException("moStream"); + if (pluralRuleGenerator == null) + throw new ArgumentNullException("pluralRuleGenerator"); + if (parser == null) + throw new ArgumentNullException("parser"); + + this._MoStream = moStream; + this.PluralRuleGenerator = pluralRuleGenerator; + this.Parser = parser; + } + + public MoLoader(string domain, string localeDir) + : this(domain, localeDir, new DefaultPluralRuleGenerator(), new MoFileParser()) + { + } + + public MoLoader(string filePath) + : this(filePath, new DefaultPluralRuleGenerator(), new MoFileParser()) + { + } + + public MoLoader(Stream moStream) + : this(moStream, new DefaultPluralRuleGenerator(), new MoFileParser()) + { + } + + + /// + /// Loads translations to the specified catalog using catalog's culture info. + /// + /// A catalog instance to load translations to. + public void Load(Catalog catalog) + { + if (this._MoStream != null) + { + this.Load(this._MoStream, catalog); + } + else if (this._FilePath != null) + { + this.Load(this._FilePath, catalog); + } + else + { + this.Load(this._Domain, this._LocaleDir, catalog); + } + } + + protected virtual void Load(string domain, string localeDir, Catalog catalog) + { + var path = this.FindTranslationFile(catalog.CultureInfo, domain, localeDir); + if (path == null) + { + throw new FileNotFoundException(String.Format("Can not find MO file name in locale directory \"{0}\".", localeDir)); + } + + this.Load(path, catalog); + } + + protected virtual void Load(string filePath, Catalog catalog) + { + Trace.WriteLine(String.Format("Loading translations from file \"{0}\"...", filePath), "NGettext"); + using (var stream = File.OpenRead(filePath)) + { + this.Load(stream, catalog); + } + } + + protected virtual void Load(Stream moStream, Catalog catalog) + { + var parser = this.Parser; + parser.Parse(moStream); + + this.Load(parser, catalog); + } + + protected virtual void Load(MoFileParser parser, Catalog catalog) + { + foreach (var translation in parser.Translations) + { + catalog.Translations.Add(translation.Key, translation.Value); + } + + if (parser.Headers.ContainsKey("Plural-Forms")) + { + var generator = this.PluralRuleGenerator as IPluralRuleTextParser; + if (generator != null) + { + generator.SetPluralRuleText(parser.Headers["Plural-Forms"]); + } + } + catalog.PluralRule = this.PluralRuleGenerator.CreateRule(catalog.CultureInfo); + } + + protected virtual string FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) + { + var possibleFiles = new[] { + this.GetFileName(localeDir, domain, cultureInfo.Name), + this.GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) + }; + + foreach (var possibleFilePath in possibleFiles) + { + if (File.Exists(possibleFilePath)) + { + return possibleFilePath; + } + } + + return null; + } + + protected virtual string GetFileName(string localeDir, string domain, string locale) + { + var relativePath = + locale.Replace('-', '_') + Path.DirectorySeparatorChar + + "LC_MESSAGES" + Path.DirectorySeparatorChar + + domain + ".mo"; + + return Path.Combine(localeDir, relativePath); + } + } +} \ No newline at end of file diff --git a/src/NGettext/NGettext.csproj b/src/NGettext/NGettext.csproj index 0900766..6a09e6f 100644 --- a/src/NGettext/NGettext.csproj +++ b/src/NGettext/NGettext.csproj @@ -44,18 +44,22 @@ - + + + + + - + - \ No newline at end of file diff --git a/src/NGettext.Tests/packages.config b/src/NGettext.Tests/packages.config deleted file mode 100644 index 24af581..0000000 --- a/src/NGettext.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/NGettext.sln b/src/NGettext.sln deleted file mode 100644 index 28bda55..0000000 --- a/src/NGettext.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext", "NGettext\NGettext.csproj", "{96EED5F5-7E90-4BD8-A822-2D7BFF943E28}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NGettext.Tests", "NGettext.Tests\NGettext.Tests.csproj", "{B150FBC7-210F-4E79-B18D-3E45532067AC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28}.Release|Any CPU.Build.0 = Release|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B150FBC7-210F-4E79-B18D-3E45532067AC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/NGettext.sln.DotSettings b/src/NGettext.sln.DotSettings deleted file mode 100644 index 123ee36..0000000 --- a/src/NGettext.sln.DotSettings +++ /dev/null @@ -1,14 +0,0 @@ - - DO_NOT_SHOW - 15 - System - On$object$$event$ - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Private fields, methods, properties..."><ElementKinds><Kind Name="FIELD" /><Kind Name="METHOD" /><Kind Name="PROPERTY" /><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /></Policy> - False - \ No newline at end of file diff --git a/src/NGettext/NGettext.csproj b/src/NGettext/NGettext.csproj deleted file mode 100644 index f69ff7e..0000000 --- a/src/NGettext/NGettext.csproj +++ /dev/null @@ -1,69 +0,0 @@ - - - - - Debug - AnyCPU - {96EED5F5-7E90-4BD8-A822-2D7BFF943E28} - Library - Properties - NGettext - NGettext - v2.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - $(DocumentationDir)NGettext.xml - $(OutputPath)NGettext.xml - - - none - true - bin\Release\ - - - prompt - 4 - $(DocumentationDir)NGettext.xml - $(OutputPath)NGettext.xml - false - - - true - ..\..\NGettext.snk - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From af9faa54ce26c73f28b6d05f5bc12cabc3ebcfb4 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 18:56:22 +0300 Subject: [PATCH 24/55] Solution files moved to match the DNX style. --- NGettext.sln | 49 +++++++++++++++++++++++++ appveyor.yml | 2 +- global.json | 6 +++ src/NGettext.Tests/NGettext.Tests.xproj | 37 ++++++++++--------- src/NGettext.vs2015.sln | 28 -------------- src/NGettext/NGettext.xproj | 39 ++++++++++---------- src/global.json | 6 --- 7 files changed, 96 insertions(+), 71 deletions(-) create mode 100644 NGettext.sln create mode 100644 global.json delete mode 100644 src/NGettext.vs2015.sln delete mode 100644 src/global.json diff --git a/NGettext.sln b/NGettext.sln new file mode 100644 index 0000000..978c949 --- /dev/null +++ b/NGettext.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{11866FB2-5A5E-45EC-99D2-690156524ED9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B2C3CAAC-6C5B-48C2-9895-964882670F4D}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + EndProjectSection +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext", "src\NGettext\NGettext.xproj", "{A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E9CE19D0-FF12-4ACE-86D2-5B649D56E11C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{954C9D61-96B7-42FD-BD5A-EA7AC483668C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{4AAD088A-469B-4766-81D9-E0878F20638F}" + ProjectSection(SolutionItems) = preProject + doc\examples\T.cs = doc\examples\T.cs + EndProjectSection +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext.Tests", "src\NGettext.Tests\NGettext.Tests.xproj", "{006D0C2E-C347-4E1F-BA5B-CE075BA25B18}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}.Release|Any CPU.Build.0 = Release|Any CPU + {006D0C2E-C347-4E1F-BA5B-CE075BA25B18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {006D0C2E-C347-4E1F-BA5B-CE075BA25B18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {006D0C2E-C347-4E1F-BA5B-CE075BA25B18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {006D0C2E-C347-4E1F-BA5B-CE075BA25B18}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7} = {11866FB2-5A5E-45EC-99D2-690156524ED9} + {4AAD088A-469B-4766-81D9-E0878F20638F} = {954C9D61-96B7-42FD-BD5A-EA7AC483668C} + {006D0C2E-C347-4E1F-BA5B-CE075BA25B18} = {E9CE19D0-FF12-4ACE-86D2-5B649D56E11C} + EndGlobalSection +EndGlobal diff --git a/appveyor.yml b/appveyor.yml index a281373..d4d731c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,2 +1,2 @@ build: - project: src/NGettext.sln \ No newline at end of file + project: NGettext.sln \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 0000000..30f0484 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "projects": [ "src", "test" ], + "sdk": { + "version": "1.0.0-rc1-update1" + } +} diff --git a/src/NGettext.Tests/NGettext.Tests.xproj b/src/NGettext.Tests/NGettext.Tests.xproj index ef655e4..7ca0d4f 100644 --- a/src/NGettext.Tests/NGettext.Tests.xproj +++ b/src/NGettext.Tests/NGettext.Tests.xproj @@ -1,18 +1,21 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 4521064c-c0f2-4511-8552-dd7330f3d231 - NGettext.Tests - ..\NGettext\artifacts\obj\$(MSBuildProjectName) - ..\NGettext\artifacts\bin\$(MSBuildProjectName)\ - - - 2.0 - - + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 006d0c2e-c347-4e1f-ba5b-ce075ba25b18 + NGettext.Tests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + \ No newline at end of file diff --git a/src/NGettext.vs2015.sln b/src/NGettext.vs2015.sln deleted file mode 100644 index a50c312..0000000 --- a/src/NGettext.vs2015.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24627.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext", "NGettext\NGettext.xproj", "{014F713D-6A82-42DC-93B7-C216AC53082E}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext.Tests", "NGettext.Tests\NGettext.Tests.xproj", "{4521064C-C0F2-4511-8552-DD7330F3D231}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {014F713D-6A82-42DC-93B7-C216AC53082E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {014F713D-6A82-42DC-93B7-C216AC53082E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {014F713D-6A82-42DC-93B7-C216AC53082E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {014F713D-6A82-42DC-93B7-C216AC53082E}.Release|Any CPU.Build.0 = Release|Any CPU - {4521064C-C0F2-4511-8552-DD7330F3D231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4521064C-C0F2-4511-8552-DD7330F3D231}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4521064C-C0F2-4511-8552-DD7330F3D231}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4521064C-C0F2-4511-8552-DD7330F3D231}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/NGettext/NGettext.xproj b/src/NGettext/NGettext.xproj index a444302..31c10eb 100644 --- a/src/NGettext/NGettext.xproj +++ b/src/NGettext/NGettext.xproj @@ -1,19 +1,20 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 014f713d-6a82-42dc-93b7-c216ac53082e - NGettext - ..\artifacts\obj\$(MSBuildProjectName) - ..\artifacts\bin\$(MSBuildProjectName)\ - - - - 2.0 - - - \ No newline at end of file + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + a6e2d0f9-52f7-421a-a8c2-e43b3394c0b7 + NGettext + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/src/global.json b/src/global.json deleted file mode 100644 index 27fc763..0000000 --- a/src/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "projects": [ "." ], - "sdk": { - "version": "1.0.0-rc1-final" - } -} \ No newline at end of file From 4766b77949e9a3414fd03faa9ec1e700557c53ce Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 18:57:46 +0300 Subject: [PATCH 25/55] Small code style fixes. --- src/NGettext/Catalog.cs | 9 +-------- src/NGettext/Loaders/MoFileParser.cs | 12 ++---------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index da9d5f4..dd53da0 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -182,14 +182,7 @@ private string _FindTranslationFile(CultureInfo cultureInfo, string domain, stri private string _GetFileName(string localeDir, string domain, string locale) { - // mono weirdness - var path1 = Path.Combine(localeDir, locale.Replace('-', '_')); - var path2 = Path.Combine("LC_MESSAGES", domain + ".mo"); - - return Path.Combine( - path1, - path2 - ); + return Path.Combine(localeDir, Path.Combine(locale.Replace('-', '_'), Path.Combine("LC_MESSAGES", domain + ".mo"))); } } } \ No newline at end of file diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index 0fe4c9b..ae11b90 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -100,11 +100,7 @@ public void Parse(Stream stream) { Trace.WriteLine("Big Endian file detected. Switching readers...", "NGettext"); this.IsBigEndian = true; -#if DNXCORE50 - reader.Dispose(); -#else - reader.Close(); -#endif + ((IDisposable)reader).Dispose(); reader = new BigEndianBinaryReader(new ReadOnlyStreamWrapper(stream)); } else @@ -200,11 +196,7 @@ public void Parse(Stream stream) } finally { -#if DNXCORE50 - reader.Dispose(); -#else - reader.Close(); -#endif + ((IDisposable)reader).Dispose(); } } From f21e2428c97daea3337ed8e26e0189e66d4bb5b0 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:00:06 +0300 Subject: [PATCH 26/55] NAnt-related files removed. --- NGettext.build | 163 --------------- NGettext.nuspec | 22 -- build.bat | 6 - build.conf.dist | 17 -- tools/mdoc/assembly_list.csv | 1 - tools/mdoc/doctemplate.xsl | 378 ----------------------------------- tools/nuget/NuGet.exe | Bin 1664512 -> 0 bytes tools/nuget/NuGet.targets | 138 ------------- 8 files changed, 725 deletions(-) delete mode 100644 NGettext.build delete mode 100644 NGettext.nuspec delete mode 100644 build.bat delete mode 100644 build.conf.dist delete mode 100644 tools/mdoc/assembly_list.csv delete mode 100644 tools/mdoc/doctemplate.xsl delete mode 100644 tools/nuget/NuGet.exe delete mode 100644 tools/nuget/NuGet.targets diff --git a/NGettext.build b/NGettext.build deleted file mode 100644 index 062bda3..0000000 --- a/NGettext.build +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NGettext.nuspec b/NGettext.nuspec deleted file mode 100644 index 7ed9ce0..0000000 --- a/NGettext.nuspec +++ /dev/null @@ -1,22 +0,0 @@ - - - - NGettext - 0.2.2.1 - Neris Ereptoris - Neris Ereptoris - https://raw.githubusercontent.com/neris/NGettext/master/LICENSE - https://github.com/neris/NGettext - false - NGettext - A .NET implementation of the GNU/Gettext library. - Initial NuGet release. - Copyright (C) 2012 Neris Ereptoris - ngettext gettext internationalization localization i18n l10n translate gnu mono - - - - - - - \ No newline at end of file diff --git a/build.bat b/build.bat deleted file mode 100644 index 997c7f3..0000000 --- a/build.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -:: Quick build with default options - -cmd /k "nant && exit" -pause diff --git a/build.conf.dist b/build.conf.dist deleted file mode 100644 index b7bda88..0000000 --- a/build.conf.dist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/mdoc/assembly_list.csv b/tools/mdoc/assembly_list.csv deleted file mode 100644 index 456327b..0000000 --- a/tools/mdoc/assembly_list.csv +++ /dev/null @@ -1 +0,0 @@ -NGettext;dll \ No newline at end of file diff --git a/tools/mdoc/doctemplate.xsl b/tools/mdoc/doctemplate.xsl deleted file mode 100644 index 176868c..0000000 --- a/tools/mdoc/doctemplate.xsl +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - <xsl:value-of select="Title" /> - - - - - - - - - - - - - - -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - -

- - - - - - -

-
- - -

- - - - - - -

-
- - -
- - - - - - -
-
- - -
- - - - - - -
-
- - -
- - - - - - -
-
- - - - -
diff --git a/tools/nuget/NuGet.exe b/tools/nuget/NuGet.exe deleted file mode 100644 index 9ca66594f912a1fe7aec510819006fb1a80bc1a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1664512 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

  • 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

    w}k|O3;Ng3Ak`gW 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 z zpXaYP$LY5z1M|9koI^Wb&i8|`rw{U5jJ=4k&lj`{6Xuug{g?JUF!$rIxDof|kO^sz z2XI~=VCSi9e)YP8A?A1lx>Qks^vVAHc{XmhoPQ33`mM+5TNIOTS_6vu+q#bHW839? z0(R_s5*}A~pZD3iAGRO#=f}Ana{J+s>w)jzb8x=rn=mY1F=0eBA%8s`e-Fpm4)<@# zoPJXjcH5x;#H_>WUe07Yw!hTvH8H=zxNf;?$gXa`Y&U3!$AR3>|7h|-zo3Tv{BOtE z5Bs(6S15<)=<7TM?^|eFoPOUXKwLN1FD??;%sY@dE4iF~@t> zaX-h`0jIO=EiC#4{02Fv4|3ao(JvgD^BnfZRfiaRA#dHz5fs<&ACG|_9v=;dt{9x_ zg|;t&WH6!E3EOJ*j{)3IJg=0 zYr~Le+iIM~qyLgeM4xl*^}i3o?4*!>R|oMC2z$y8=kH4Bf+3FswiWX8DnEbQ_sL;# z73a&0&uJ~bdCwfi{f~Zc51iYRjr;HIIe+Z`PS~@d9lz^-kkfNG)#yT4w@2#=kdBWB z!#nW)+pag@>oy|(VtA^UZ^9IB+!0LA=Y8uT{hAEY2ahx7FnFBfTz($^@w_*WgILFQ zIBZ4#!N-%s?&C5p7vFDYZ=>E=&;9fwGY`z`DMKRLjQePwEQ#}RKeX$4LgE$p<8f

    >2--I}aFCqV3hWqn}_Ps+y^e(pjbMW|1 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 RGHFl)S5g03{{M}@-vCWeV3Gg; diff --git a/tools/nuget/NuGet.targets b/tools/nuget/NuGet.targets deleted file mode 100644 index 4f62798..0000000 --- a/tools/nuget/NuGet.targets +++ /dev/null @@ -1,138 +0,0 @@ - - - - $(MSBuildProjectDirectory)\..\ - - - false - - - false - - - true - - - false - - - - - - - - - - $(SolutionDir)/../tools/nuget - - - - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config - - - - $(MSBuildProjectDirectory)\packages.config - $(PackagesProjectConfig) - - - - - $(NuGetToolsPath)\NuGet.exe - @(PackageSource) - - "$(NuGetExePath)" - mono --runtime=v4.0.30319 "$(NuGetExePath)" - - $(TargetDir.Trim('\\')) - - -RequireConsent - -NonInteractive - - "$(SolutionDir) " - "$(SolutionDir)" - - - $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) - $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols - - - - RestorePackages; - $(BuildDependsOn); - - - - - $(BuildDependsOn); - BuildPackage; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 897f1f17df7930fad792615eeacc0a8aad7d07cc Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:03:09 +0300 Subject: [PATCH 27/55] Project file updated: Metadata, key file and target platforms updated; Assembly Guid for .NET Core fix. --- src/NGettext/Properties/AssemblyInfo.cs | 2 - src/NGettext/project.json | 133 ++++++++++++++++++------ 2 files changed, 102 insertions(+), 33 deletions(-) diff --git a/src/NGettext/Properties/AssemblyInfo.cs b/src/NGettext/Properties/AssemblyInfo.cs index 3dbcc8f..8ea174c 100644 --- a/src/NGettext/Properties/AssemblyInfo.cs +++ b/src/NGettext/Properties/AssemblyInfo.cs @@ -16,9 +16,7 @@ [assembly: AssemblyVersion("0.2.2.1")] [assembly: AssemblyFileVersion("0.2.2.1")] -#if !DNXCORE50 [assembly: Guid("9ef9b9d7-7df8-4c3a-ac8c-58bea65f0526")] -#endif [assembly: ComVisible(true)] [assembly: CLSCompliant(true)] diff --git a/src/NGettext/project.json b/src/NGettext/project.json index a2106de..0949224 100644 --- a/src/NGettext/project.json +++ b/src/NGettext/project.json @@ -1,31 +1,102 @@ -{ - "version": "1.0.0-rc1-*", - "description": "NGettext", - "authors": [ "Neris Ereptoris" ], - "tags": [ "gettext", "i18n", "localization" ], - "projectUrl": "https://github.com/neris/NGettext", - "licenseUrl": "https://github.com/neris/NGettext/blob/master/LICENSE", - - "dependencies": { - - }, - - "frameworks": { - "net20": { }, - "net45": { }, - "dnx451": { }, - "dnxcore50": { - "dependencies": { - "System.Runtime": "4.0.21-beta-23516", - "System.Globalization": "4.0.11-beta-23516", - "System.Collections": "4.0.0-beta-23019", - "System.IO": "4.0.11-beta-23516", - "System.Diagnostics.Debug": "4.0.0-beta-23019", - "System.Runtime.Extensions": "4.0.0-beta-23019", - "System.Text.RegularExpressions": "4.0.0-beta-23019", - "System.Diagnostics.TraceSource": "4.0.0-beta-23516", - "System.IO.FileSystem": "4.0.1-beta-23516" - } - } - } -} \ No newline at end of file +{ + "version": "0.3.0.0", + "title": "NGettext", + "description": "A .NET implementation of the GNU/Gettext library.", + "owners": [ "Neris Ereptoris" ], + "authors": [ "Neris Ereptoris" ], + "tags": [ "ngettext", "gettext", "internationalization", "localization", "i18n", "l10n", "translate" ], + "projectUrl": "https://github.com/neris/NGettext", + "licenseUrl": "https://raw.githubusercontent.com/neris/NGettext/master/LICENSE", + "requireLicenseAcceptance": false, + + "repository": { + "type": "git", + "url": "git://github.com/neris/NGettext" + }, + + "compilationOptions": { + "languageVersion": "csharp6", + "keyFile": "..\\..\\NGettext.snk" + }, + + "packInclude": { + "LICENSE": "..\\..\\LICENSE" + }, + + "dependencies": { + }, + + "frameworks": { + "net20": { + "frameworkAssemblies": { + "System": "" + } + }, + "net35": { + "frameworkAssemblies": { + "System": "" + } + }, + "net35-client": { + "frameworkAssemblies": { + "System": "" + } + }, + "net40": { + "frameworkAssemblies": { + "System": "" + } + }, + "net40-client": { + "frameworkAssemblies": { + "System": "" + } + }, + "net45": { + "frameworkAssemblies": { + "System": "" + } + }, + "net46": { + "frameworkAssemblies": { + "System": "" + } + }, + "dnx451": { + "frameworkAssemblies": { + "System": "" + } + }, + "dnxcore50": { + "dependencies": { + "Microsoft.CSharp": "4.0.1-beta-23516", + "System.Runtime": "4.0.21-beta-23516", + "System.Globalization": "4.0.11-beta-23516", + "System.Collections": "4.0.0-beta-23019", + "System.IO": "4.0.11-beta-23516", + "System.Diagnostics.Debug": "4.0.0-beta-23019", + "System.Runtime.Extensions": "4.0.0-beta-23019", + "System.Text.RegularExpressions": "4.0.0-beta-23019", + "System.Diagnostics.TraceSource": "4.0.0-beta-23516", + "System.IO.FileSystem": "4.0.1-beta-23516" + } + }, + "uap10.0": { + "dependencies": { + "Microsoft.CSharp": "4.0.1-beta-23516", + "System.Runtime": "4.0.21-beta-23516", + "System.Globalization": "4.0.11-beta-23516", + "System.Collections": "4.0.0-beta-23019", + "System.IO": "4.0.11-beta-23516", + "System.Diagnostics.Debug": "4.0.0-beta-23019", + "System.Runtime.Extensions": "4.0.0-beta-23019", + "System.Text.RegularExpressions": "4.0.0-beta-23019", + "System.Diagnostics.TraceSource": "4.0.0-beta-23516", + "System.IO.FileSystem": "4.0.1-beta-23516" + }, + "compilationOptions": { + "define": [ "DNXCORE50" ] + } + } + } +} From 25df55cc0777a6219db468e0aa55eefe38e7dcdd Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:08:43 +0300 Subject: [PATCH 28/55] Tests migrated to the Xunit framework. --- src/NGettext.Tests/App.config | 13 -- src/NGettext.Tests/BaseCatalogTest.cs | 169 ++++++++---------- src/NGettext.Tests/CatalogTest.cs | 37 ++-- .../Loaders/MoFileParserTest.cs | 32 ++-- .../Plural/DefaultPluralRuleGeneratorTest.cs | 17 +- src/NGettext.Tests/Plural/PluralRuleTest.cs | 19 +- src/NGettext.Tests/Program.cs | 22 --- src/NGettext.Tests/Properties/AssemblyInfo.cs | 23 +-- src/NGettext.Tests/project.json | 63 +++---- 9 files changed, 142 insertions(+), 253 deletions(-) delete mode 100644 src/NGettext.Tests/App.config delete mode 100644 src/NGettext.Tests/Program.cs diff --git a/src/NGettext.Tests/App.config b/src/NGettext.Tests/App.config deleted file mode 100644 index 25b4ef6..0000000 --- a/src/NGettext.Tests/App.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/src/NGettext.Tests/BaseCatalogTest.cs index 7e5da35..f9c0112 100644 --- a/src/NGettext.Tests/BaseCatalogTest.cs +++ b/src/NGettext.Tests/BaseCatalogTest.cs @@ -1,26 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; - -using NUnit.Framework; - +using System.Globalization; +using Xunit; using NGettext.Tests.Stabs; namespace NGettext.Tests { - [TestFixture] public class BaseCatalogTest { - [SetUp] - public void Init() - { - - } #region GetString - [Test] + [Fact] public void TestGetString() { var t = new EmptyBaseCatalog(); @@ -29,99 +18,99 @@ public void TestGetString() t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); t.Translations.Add("", new[] { "emptyIdValue" }); - Assert.AreEqual("value1", t.GetString("key1")); - Assert.AreEqual("value2", t.GetString("key2")); - Assert.AreEqual("value3plural1", t.GetString("key3")); - Assert.AreEqual("notFoundKey2", t.GetString("notFoundKey2")); - Assert.AreEqual("", t.GetString("")); + Assert.Equal("value1", t.GetString("key1")); + Assert.Equal("value2", t.GetString("key2")); + Assert.Equal("value3plural1", t.GetString("key3")); + Assert.Equal("notFoundKey2", t.GetString("notFoundKey2")); + Assert.Equal("", t.GetString("")); } - [Test] + [Fact] public void TestGetStringFormat() { var t = new EmptyBaseCatalog(); - Assert.AreEqual("Foo bar", t.GetString("Foo {0}", "bar")); - Assert.AreEqual("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); - Assert.AreEqual("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); + Assert.Equal("Foo bar", t.GetString("Foo {0}", "bar")); + Assert.Equal("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); + Assert.Equal("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); } - [Test] + [Fact] public void TestGetStringFormatCulture() { var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - Assert.AreEqual("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); - Assert.AreEqual("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); + Assert.Equal("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); } #endregion #region GetPluralString - [Test] + [Fact] public void TestGetPluralString() { var t = new EmptyBaseCatalog(new CultureInfo("en-US")); t.Translations.Add("key1", new[] {"value1"}); t.Translations.Add("key2plural1", new[] {"value2plural1", "value2plural2"}); - Assert.AreEqual("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); - Assert.AreEqual("value1", t.GetPluralString("key1", "key1", 1)); - Assert.AreEqual("key1plural", t.GetPluralString("key1", "key1plural", 2)); + Assert.Equal("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); + Assert.Equal("value1", t.GetPluralString("key1", "key1", 1)); + Assert.Equal("key1plural", t.GetPluralString("key1", "key1plural", 2)); - Assert.AreEqual("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); - Assert.AreEqual("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); + Assert.Equal("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); + Assert.Equal("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); } - [Test] + [Fact] public void TestGetPluralStringFormat() { var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - Assert.AreEqual("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.AreEqual("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.AreEqual("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); + Assert.Equal("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.Equal("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.Equal("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); - Assert.AreEqual("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); - Assert.AreEqual("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); - Assert.AreEqual("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); + Assert.Equal("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); + Assert.Equal("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); + Assert.Equal("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); } - [Test] + [Fact] public void TestGetPluralStringInternational() { var t = new EmptyBaseCatalog(new CultureInfo("ru-RU")); t.Translations.Add("You have {0} apple", new[] { "У Вас {0} яблоко", "У Вас {0} яблока", "У Вас {0} яблок" }); - Assert.AreEqual("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.AreEqual("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.AreEqual("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); - Assert.AreEqual("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); - Assert.AreEqual("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); - Assert.AreEqual("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); - Assert.AreEqual("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); - Assert.AreEqual("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); + Assert.Equal("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.Equal("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.Equal("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); + Assert.Equal("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); + Assert.Equal("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); + Assert.Equal("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); + Assert.Equal("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); + Assert.Equal("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); - Assert.AreEqual("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); + Assert.Equal("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); } - [Test] + [Fact] public void TestGetPluralStringFormatCulture() { var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - Assert.AreEqual("Foo 1.23", catalogEn.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); - Assert.AreEqual("Foo 1,23", catalogRu.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1.23", catalogEn.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); } #endregion #region GetParticularString - [Test] + [Fact] public void TestGetParticularString() { var t = new EmptyBaseCatalog(); @@ -129,97 +118,97 @@ public void TestGetParticularString() t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value2" }); t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value3" }); - Assert.AreEqual("value1", t.GetString("key1")); - Assert.AreEqual("value2", t.GetParticularString("context1", "key1")); - Assert.AreEqual("value3", t.GetParticularString("context2", "key1")); - Assert.AreEqual("key1", t.GetParticularString("context3", "key1")); + Assert.Equal("value1", t.GetString("key1")); + Assert.Equal("value2", t.GetParticularString("context1", "key1")); + Assert.Equal("value3", t.GetParticularString("context2", "key1")); + Assert.Equal("key1", t.GetParticularString("context3", "key1")); } - [Test] + [Fact] public void TestGetParticularStringFormat() { var t = new EmptyBaseCatalog(); - Assert.AreEqual("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); - Assert.AreEqual("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); + Assert.Equal("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); + Assert.Equal("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); } - [Test] + [Fact] public void TestGetParticularStringFormatCulture() { var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - Assert.AreEqual("Foo 1.23", catalogEn.GetParticularString("context", "Foo {0}", 1.23)); - Assert.AreEqual("Foo 1,23", catalogRu.GetParticularString("context", "Foo {0}", 1.23)); + Assert.Equal("Foo 1.23", catalogEn.GetParticularString("context", "Foo {0}", 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetParticularString("context", "Foo {0}", 1.23)); } #endregion #region GetParticularPluralString - [Test] + [Fact] public void TestGetParticularPluralString() { var t = new EmptyBaseCatalog(new CultureInfo("en-US")); t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); - Assert.AreEqual("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); - Assert.AreEqual("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); - Assert.AreEqual("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); - Assert.AreEqual("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); + Assert.Equal("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); + Assert.Equal("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); + Assert.Equal("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); + Assert.Equal("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); } - [Test] + [Fact] public void TestGetParticularPluralStringFormat() { var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - Assert.AreEqual("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); - Assert.AreEqual("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); - Assert.AreEqual("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); - Assert.AreEqual("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); + Assert.Equal("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); + Assert.Equal("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); + Assert.Equal("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); + Assert.Equal("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); } - [Test] + [Fact] public void TestGetParticularPluralStringFormatCulture() { var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - Assert.AreEqual("Foo 1.23", catalogEn.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); - Assert.AreEqual("Foo 1,23", catalogRu.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1.23", catalogEn.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); } #endregion #region *Default methods - [Test] + [Fact] public void TestProtectedGetString() { var t = new EmptyBaseCatalog(); t.Translations.Add("key1", new[] { "value1" }); - Assert.AreEqual("value1", t.GetStringDefault("key1", null)); - Assert.AreEqual(null, t.GetStringDefault("key2", null)); - Assert.AreEqual("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); + Assert.Equal("value1", t.GetStringDefault("key1", null)); + Assert.Equal(null, t.GetStringDefault("key2", null)); + Assert.Equal("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); } - [Test] + [Fact] public void TestProtectedGetPluralString() { var t = new EmptyBaseCatalog(new CultureInfo("en-US")); t.Translations.Add("key1", new[] { "value1" }); - Assert.AreEqual("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); - Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); - Assert.AreEqual("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); - Assert.AreEqual("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); + Assert.Equal("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); + Assert.Equal("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); + Assert.Equal("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); + Assert.Equal("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); } - [Test] + [Fact] public void TestProtectedGetTranslations() { var t = new EmptyBaseCatalog(); @@ -227,10 +216,10 @@ public void TestProtectedGetTranslations() t.Translations.Add("key2", new[] { "value2" }); t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - Assert.AreEqual(new[] { "value1" }, t.GetTranslations("key1")); - Assert.AreEqual(new[] { "value2" }, t.GetTranslations("key2")); - Assert.AreEqual(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); - Assert.AreEqual(null, t.GetTranslations("key4")); + Assert.Equal(new[] { "value1" }, t.GetTranslations("key1")); + Assert.Equal(new[] { "value2" }, t.GetTranslations("key2")); + Assert.Equal(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); + Assert.Equal(null, t.GetTranslations("key4")); } #endregion diff --git a/src/NGettext.Tests/CatalogTest.cs b/src/NGettext.Tests/CatalogTest.cs index 7ba22c3..c4bbff4 100644 --- a/src/NGettext.Tests/CatalogTest.cs +++ b/src/NGettext.Tests/CatalogTest.cs @@ -1,38 +1,31 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; +using System.Globalization; using System.IO; -using System.Reflection; - -using NUnit.Framework; +using Xunit; namespace NGettext.Tests { - [TestFixture] public class CatalogTest { public string LocalesDir; - [SetUp] - public void Init() + public CatalogTest() { this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); } - [Test] + [Fact] public void TestEmpty() { var t = new Catalog(); - Assert.AreEqual(0, t.Translations.Count); - Assert.AreEqual(CultureInfo.CurrentUICulture, t.CultureInfo); + Assert.Equal(0, t.Translations.Count); + Assert.Equal(CultureInfo.CurrentUICulture, t.CultureInfo); t = new Catalog(new CultureInfo("fr")); - Assert.AreEqual(new CultureInfo("fr"), t.CultureInfo); + Assert.Equal(new CultureInfo("fr"), t.CultureInfo); } - [Test] + [Fact] public void TestStream() { using (var stream = File.OpenRead(Path.Combine(this.LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) @@ -42,7 +35,7 @@ public void TestStream() } } - [Test] + [Fact] public void TestLocaleDir() { var t = new Catalog("Test", this.LocalesDir, new CultureInfo("ru-RU")); @@ -51,13 +44,13 @@ public void TestLocaleDir() private void _TestLoadedTranslation(ICatalog t) { - Assert.AreEqual("тест", t.GetString("test")); - Assert.AreEqual("тест2", t.GetString("test2")); - Assert.AreEqual("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); - Assert.AreEqual("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); + Assert.Equal("тест", t.GetString("test")); + Assert.Equal("тест2", t.GetString("test2")); + Assert.Equal("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); + Assert.Equal("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); - Assert.AreEqual("тест3контекст1", t.GetParticularString("context1", "test3")); - Assert.AreEqual("тест3контекст2", t.GetParticularString("context2", "test3")); + Assert.Equal("тест3контекст1", t.GetParticularString("context1", "test3")); + Assert.Equal("тест3контекст2", t.GetParticularString("context2", "test3")); } } diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 5fb83c7..72a7b8d 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -1,27 +1,21 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Text; using System.IO; -using System.Reflection; - -using NUnit.Framework; - +using Xunit; using NGettext.Loaders; namespace NGettext.Tests.Loaders { - [TestFixture] public class MoFileParserTest { public string LocalesDir; - - [SetUp] - public void Init() + + public MoFileParserTest() { this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); } - [Test] + [Fact] public void TestParsing() { using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) @@ -32,7 +26,7 @@ public void TestParsing() } } - [Test] + [Fact] public void TestBigEndianParsing() { using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_BigEndian.mo"))))) @@ -43,7 +37,7 @@ public void TestBigEndianParsing() } } - [Test] + [Fact] public void TestAutoEncoding() { using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_KOI8-R.mo"))))) @@ -54,7 +48,7 @@ public void TestAutoEncoding() } } - [Test] + [Fact] public void TestManualEncoding() { using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_KOI8-R.mo"))))) @@ -71,11 +65,11 @@ public void TestManualEncoding() private void _TestLoadedTranslation(IDictionary dict) { - Assert.AreEqual(new[] { "тест" }, dict["test"]); - Assert.AreEqual(new[] { "тест2" }, dict["test2"]); - Assert.AreEqual(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.AreEqual(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.AreEqual(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.Equal(new[] { "тест" }, dict["test"]); + Assert.Equal(new[] { "тест2" }, dict["test2"]); + Assert.Equal(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); + Assert.Equal(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.Equal(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); } } } \ No newline at end of file diff --git a/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs b/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs index c56cbe6..35070a9 100644 --- a/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs +++ b/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs @@ -1,24 +1,15 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Globalization; -using System.Text; using NGettext.Plural; -using NUnit.Framework; +using Xunit; namespace NGettext.Tests.Plural { - [TestFixture] public class DefaultPluralRuleGeneratorTest { - [SetUp] - public void Init() - { - - } - #region Default forms - [Test] + [Fact] public void TestDefaultForms() { var dict = new Dictionary>() @@ -112,7 +103,7 @@ public void TestDefaultForms() var rule = generator.CreateRule(locale); foreach (var data in testCase.Value) { - Assert.AreEqual(data.Value, rule.Evaluate(data.Key)); + Assert.Equal(data.Value, rule.Evaluate(data.Key)); } } } diff --git a/src/NGettext.Tests/Plural/PluralRuleTest.cs b/src/NGettext.Tests/Plural/PluralRuleTest.cs index d3917fc..b73d46d 100644 --- a/src/NGettext.Tests/Plural/PluralRuleTest.cs +++ b/src/NGettext.Tests/Plural/PluralRuleTest.cs @@ -1,24 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; +using Xunit; using NGettext.Plural; -using NUnit.Framework; namespace NGettext.Tests.Plural { - [TestFixture] public class PluralRuleTest { - [SetUp] - public void Init() - { - - } - #region Custom forms - [Test] + [Fact] public void TestCustomForms() { var rule1 = new PluralRule(1, number => (int)number); @@ -26,8 +15,8 @@ public void TestCustomForms() foreach (var n in new long[] { 0, 1, 2, 3, 100, 101, 102, 103 }) { - Assert.AreEqual(n, rule1.Evaluate(n)); - Assert.AreEqual(n * 2, rule2.Evaluate(n)); + Assert.Equal(n, rule1.Evaluate(n)); + Assert.Equal(n * 2, rule2.Evaluate(n)); } } diff --git a/src/NGettext.Tests/Program.cs b/src/NGettext.Tests/Program.cs deleted file mode 100644 index f434868..0000000 --- a/src/NGettext.Tests/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using NUnitLite; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace NGettext.Tests -{ - public class Program - { - // http://www.alteridem.net/2015/11/04/testing-net-core-using-nunit-3/ - public static int Main(string[] args) - { -#if DNXCORE50 - - return new AutoRun().Execute(typeof(Program).GetTypeInfo().Assembly, Console.Out, Console.In, args); -#else - return new AutoRun().Execute(args); -#endif - } - } -} diff --git a/src/NGettext.Tests/Properties/AssemblyInfo.cs b/src/NGettext.Tests/Properties/AssemblyInfo.cs index 57faece..8ccd9ec 100644 --- a/src/NGettext.Tests/Properties/AssemblyInfo.cs +++ b/src/NGettext.Tests/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Tests")] +[assembly: AssemblyTitle("NGettext.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Tests")] -[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyProduct("NGettext.Tests")] +[assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -19,20 +19,5 @@ // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -#if !DNXCORE50 // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("963df97c-de1a-4860-aae0-8657970d165c")] -#endif - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: Guid("006d0c2e-c347-4e1f-ba5b-ce075ba25b18")] diff --git a/src/NGettext.Tests/project.json b/src/NGettext.Tests/project.json index f96a568..42d0369 100644 --- a/src/NGettext.Tests/project.json +++ b/src/NGettext.Tests/project.json @@ -1,40 +1,23 @@ -{ - "version": "1.0.0-rc1-*", - "description": "NGettext", - "authors": [ "Neris Ereptoris" ], - "tags": [ "gettext", "i18n", "localization" ], - "projectUrl": "https://github.com/neris/NGettext", - "licenseUrl": "https://github.com/neris/NGettext/blob/master/LICENSE", - - "compilationOptions": { - "emitEntryPoint": true - }, - - "dependencies": { - "NUnit": "3.0.0", - "NUnitLite": "3.0.0", - - "NGettext": "" - }, - - "commands": { - "test": "NGettext.Tests" - }, - - "frameworks": { - "net20": { }, - "net45": { }, - "dnx451": { }, - "dnxcore50": { - "dependencies": { - "System.Runtime": "4.0.21-beta-23516", - "System.Globalization": "4.0.11-beta-23516", - "System.Collections": "4.0.0-beta-23019", - "System.IO": "4.0.11-beta-23516", - "System.Console": "4.0.0-beta-23516", - "System.Text.Encoding.CodePages": "4.0.1-beta-23516", - "System.Reflection": "4.1.0-beta-23516" - } - } - } -} \ No newline at end of file +{ + "version": "1.0.0-*", + "description": "NGettext Tests", + "authors": [ "Neris Ereptoris" ], + "tags": [ "" ], + "projectUrl": "", + "licenseUrl": "", + + "dependencies": { + "xunit": "2.1.0", + "xunit.runner.dnx": "2.1.0-rc1-build204", + + "NGettext": { "target": "project" } + }, + "commands": { + "test": "xunit.runner.dnx" + }, + + "frameworks": { + "dnx46": { }, + "dnxcore50": { } + } +} From a62c3fdc94c0dab76ba7dcb11e7338c7eb355586 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:10:15 +0300 Subject: [PATCH 29/55] CodePages fix for tests running under .NET Core runtime. --- src/NGettext.Tests/Loaders/MoFileParserTest.cs | 3 +++ src/NGettext.Tests/project.json | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/src/NGettext.Tests/Loaders/MoFileParserTest.cs index 72a7b8d..14a9974 100644 --- a/src/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/src/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -13,6 +13,9 @@ public class MoFileParserTest public MoFileParserTest() { this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); +#if DNXCORE50 + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); +#endif } [Fact] diff --git a/src/NGettext.Tests/project.json b/src/NGettext.Tests/project.json index 42d0369..bfa0a35 100644 --- a/src/NGettext.Tests/project.json +++ b/src/NGettext.Tests/project.json @@ -18,6 +18,10 @@ "frameworks": { "dnx46": { }, - "dnxcore50": { } + "dnxcore50": { + "dependencies": { + "System.Text.Encoding.CodePages": "4.0.1-beta-23409" + } + } } } From c087c71ad109f923752371fe90e0e9fb74bf7937 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:10:35 +0300 Subject: [PATCH 30/55] Version bump. --- VERSION | 2 +- src/NGettext/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 6d2337b..73082a8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.2.1 \ No newline at end of file +0.3.0.0 \ No newline at end of file diff --git a/src/NGettext/Properties/AssemblyInfo.cs b/src/NGettext/Properties/AssemblyInfo.cs index 8ea174c..b16c022 100644 --- a/src/NGettext/Properties/AssemblyInfo.cs +++ b/src/NGettext/Properties/AssemblyInfo.cs @@ -13,8 +13,8 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("0.2.2.1")] -[assembly: AssemblyFileVersion("0.2.2.1")] +[assembly: AssemblyVersion("0.3.0.0")] +[assembly: AssemblyFileVersion("0.3.0.0")] [assembly: Guid("9ef9b9d7-7df8-4c3a-ac8c-58bea65f0526")] From f8dd45e62f3389e5f35697a9c54bfd9378c4ae1d Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:14:45 +0300 Subject: [PATCH 31/55] Tests project moved to the test directory. --- NGettext.sln | 2 +- {src => test}/NGettext.Tests/BaseCatalogTest.cs | 0 {src => test}/NGettext.Tests/CatalogTest.cs | 0 .../NGettext.Tests/Loaders/MoFileParserTest.cs | 0 {src => test}/NGettext.Tests/NGettext.Tests.xproj | 0 .../Plural/DefaultPluralRuleGeneratorTest.cs | 0 .../NGettext.Tests/Plural/PluralRuleTest.cs | 0 .../NGettext.Tests/Properties/AssemblyInfo.cs | 0 .../NGettext.Tests/Stabs/EmptyBaseCatalog.cs | 0 .../TestResources/locales/ru_RU/LC_MESSAGES/Test.mo | Bin .../TestResources/locales/ru_RU/LC_MESSAGES/Test.po | 0 .../locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo | Bin .../locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo | Bin .../locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po | 0 {src => test}/NGettext.Tests/project.json | 0 15 files changed, 1 insertion(+), 1 deletion(-) rename {src => test}/NGettext.Tests/BaseCatalogTest.cs (100%) rename {src => test}/NGettext.Tests/CatalogTest.cs (100%) rename {src => test}/NGettext.Tests/Loaders/MoFileParserTest.cs (100%) rename {src => test}/NGettext.Tests/NGettext.Tests.xproj (100%) rename {src => test}/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs (100%) rename {src => test}/NGettext.Tests/Plural/PluralRuleTest.cs (100%) rename {src => test}/NGettext.Tests/Properties/AssemblyInfo.cs (100%) rename {src => test}/NGettext.Tests/Stabs/EmptyBaseCatalog.cs (100%) rename {src => test}/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.mo (100%) rename {src => test}/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po (100%) rename {src => test}/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo (100%) rename {src => test}/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo (100%) rename {src => test}/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po (100%) rename {src => test}/NGettext.Tests/project.json (100%) diff --git a/NGettext.sln b/NGettext.sln index 978c949..1cbd48b 100644 --- a/NGettext.sln +++ b/NGettext.sln @@ -21,7 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{4A doc\examples\T.cs = doc\examples\T.cs EndProjectSection EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext.Tests", "src\NGettext.Tests\NGettext.Tests.xproj", "{006D0C2E-C347-4E1F-BA5B-CE075BA25B18}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext.Tests", "test\NGettext.Tests\NGettext.Tests.xproj", "{006D0C2E-C347-4E1F-BA5B-CE075BA25B18}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/NGettext.Tests/BaseCatalogTest.cs b/test/NGettext.Tests/BaseCatalogTest.cs similarity index 100% rename from src/NGettext.Tests/BaseCatalogTest.cs rename to test/NGettext.Tests/BaseCatalogTest.cs diff --git a/src/NGettext.Tests/CatalogTest.cs b/test/NGettext.Tests/CatalogTest.cs similarity index 100% rename from src/NGettext.Tests/CatalogTest.cs rename to test/NGettext.Tests/CatalogTest.cs diff --git a/src/NGettext.Tests/Loaders/MoFileParserTest.cs b/test/NGettext.Tests/Loaders/MoFileParserTest.cs similarity index 100% rename from src/NGettext.Tests/Loaders/MoFileParserTest.cs rename to test/NGettext.Tests/Loaders/MoFileParserTest.cs diff --git a/src/NGettext.Tests/NGettext.Tests.xproj b/test/NGettext.Tests/NGettext.Tests.xproj similarity index 100% rename from src/NGettext.Tests/NGettext.Tests.xproj rename to test/NGettext.Tests/NGettext.Tests.xproj diff --git a/src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs b/test/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs similarity index 100% rename from src/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs rename to test/NGettext.Tests/Plural/DefaultPluralRuleGeneratorTest.cs diff --git a/src/NGettext.Tests/Plural/PluralRuleTest.cs b/test/NGettext.Tests/Plural/PluralRuleTest.cs similarity index 100% rename from src/NGettext.Tests/Plural/PluralRuleTest.cs rename to test/NGettext.Tests/Plural/PluralRuleTest.cs diff --git a/src/NGettext.Tests/Properties/AssemblyInfo.cs b/test/NGettext.Tests/Properties/AssemblyInfo.cs similarity index 100% rename from src/NGettext.Tests/Properties/AssemblyInfo.cs rename to test/NGettext.Tests/Properties/AssemblyInfo.cs diff --git a/src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs b/test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs similarity index 100% rename from src/NGettext.Tests/Stabs/EmptyBaseCatalog.cs rename to test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.mo b/test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.mo similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.mo rename to test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.mo diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po b/test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po rename to test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test.po diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo b/test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo rename to test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_BigEndian.mo diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo b/test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo rename to test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.mo diff --git a/src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po b/test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po similarity index 100% rename from src/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po rename to test/NGettext.Tests/TestResources/locales/ru_RU/LC_MESSAGES/Test_KOI8-R.po diff --git a/src/NGettext.Tests/project.json b/test/NGettext.Tests/project.json similarity index 100% rename from src/NGettext.Tests/project.json rename to test/NGettext.Tests/project.json From 0c6ed284a7a027c5b73bb2a0637a4adf90c93648 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:46:54 +0300 Subject: [PATCH 32/55] Appveyor fix. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index d4d731c..8e53b74 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,2 +1,5 @@ +os: Visual Studio 2015 +init: + - dnvm install latest build: project: NGettext.sln \ No newline at end of file From 9ea62159b10858d24e00e75f6e2c90f0d2d8ef9b Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 19:52:53 +0300 Subject: [PATCH 33/55] Appveyor fix. --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8e53b74..3aa5e26 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,6 @@ os: Visual Studio 2015 -init: +before_build: - dnvm install latest + - dnu restore build: project: NGettext.sln \ No newline at end of file From 02e8c49a3d04b9f8f8ba50c1a37f40d5e3e845c5 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 20:28:14 +0300 Subject: [PATCH 34/55] Appveyor snk decryption. --- NGettext.snk.enc | Bin 0 -> 608 bytes appveyor.yml | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 NGettext.snk.enc diff --git a/NGettext.snk.enc b/NGettext.snk.enc new file mode 100644 index 0000000000000000000000000000000000000000..9aab38601b7901c9917eb3061428ccaf66dc5b35 GIT binary patch literal 608 zcmV-m0-ybaY5!n!5IjONlt%rI>x=$7P!E1=y@{- znby8GLrN4xmU|8jM@~1!usG*B8W0=5BAT}5!Rmi#{VxNyR3oeeGUkd*T8Tebr(Zb~ z`pf?m)I`6E3c&-(bwMdyx$H3#!cIH8gaP5u)+lk*RER7mRThXtw!guw7#2_(^oV@s zK-bzZxcvZk@XnOSB`}^XpxQ!S@g7&kdNImr{ntls(Oc_@X!cr`*sDkZZHMm!^HOopM#M9x8T3nL0ej>-tkP%I)|+MsL~e@yOx&XSjY?6JnIOlBte61 zIugnv{F!18Sr(!ATc3e_VkRrK)lEttLc<#YYYP#i2Jy}vA{+1y;zb8Nd literal 0 HcmV?d00001 diff --git a/appveyor.yml b/appveyor.yml index 3aa5e26..c5b5a18 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,11 @@ os: Visual Studio 2015 +environment: + snk_secret: + secure: 0l0TrDvCNXH4z922G/Qa5hFG4+4payl1zRAfjMfEXRw= before_build: - dnvm install latest - dnu restore + - nuget install secure-file -ExcludeVersion + - secure-file\tools\secure-file -decrypt NGettext.snk.enc -secret %snk_secret% build: project: NGettext.sln \ No newline at end of file From 4980c78ff353757c930b5d9bb018e7357558cce6 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 20:42:42 +0300 Subject: [PATCH 35/55] Appveyor fix. --- appveyor.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c5b5a18..29203e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,10 +2,16 @@ os: Visual Studio 2015 environment: snk_secret: secure: 0l0TrDvCNXH4z922G/Qa5hFG4+4payl1zRAfjMfEXRw= -before_build: + +install: - dnvm install latest - dnu restore - nuget install secure-file -ExcludeVersion - secure-file\tools\secure-file -decrypt NGettext.snk.enc -secret %snk_secret% + build: - project: NGettext.sln \ No newline at end of file + project: NGettext.sln + +test_script: + - cd test\NGettext.Tests + - dnx test From 3af862517a1664ef91bdc7d4c6cd7d022429b68e Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:03:48 +0300 Subject: [PATCH 36/55] Travis-CI fix. --- .travis.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa82efa..ac2ff05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,18 +3,19 @@ # language: csharp -solution: src/NGettext.sln + + mono: - - 3.12.0 - - 3.2.8 + - 4.2.1 +env: + global: + - secure: "JO9BJHINLiXBe77OhScvVh25NTCSgyQdWmfHSYmemYJRXKd48JlGVX+Hg+uBD9e9JNrgihR4M+7MRD+p1DeFJa5fnlRs4sP6Urtw15/wdEoyMzfJ6IwcQgH9L00dPrjH2vXdemFQHl3v9ViUQbqNwUmANxjOHv3T2xnN7pt+IiglTRGFAPsHXSAGxlhz3XGJC9f3nrTVAr8Btwf7nAxjHutr97kvw2i83sTWvEWl26CVRb+rSu3xjoK5ze+4UXXlMNni6qkXzKnvWgYDmmrLNaU6L6GWcpkPl7bOAaPZ1833tQp0G7ZNAxCguSbCM3xfU0ujXn9szXaKD2zt2MGl/otkR3x7vSy/I2F1870zAEw9WEmVY0lsKwVv5YXASMqxc0APo1d2xAMEZYGDz7TnO/JJSGFLj/MNB7zRqrYG/rkD75V2jd3O/rXwzHQL1J9n/G9by9lq3EWYxPHZ4bF9xOCEgtD5ow27xWmcwFnF4mZNErOezwjIvmZdQXymBxM094yc/kHS30gsvS/HwzzK7Ccb04Uvqdogl9nOI2Okm85fhnkEHAK4YE+XVKxgLOLPcuSTs9qtqwe5Tte+ACkqdCeivtacWcRNInbchfbldc53VjPXZ/tRrZAm+snCkukOHF07m38JpaGuiXaBiEBvGMPbIB6vCObh3rwUnYE255Q=" install: - - sudo apt-get install nant + - nuget install secure-file -ExcludeVersion + - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret %SNK_SECRET% -script: - - nant build - - nant test +solution: src/NGettext.sln -branches: - only: - - master +script: + - xbuild src/NGettext.sln From be761c0462fa8e069c648ca2ff99388f80079543 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:13:36 +0300 Subject: [PATCH 37/55] Travis-CI fix. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ac2ff05..60c67c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ env: install: - nuget install secure-file -ExcludeVersion - - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret %SNK_SECRET% + - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" solution: src/NGettext.sln From a0ecbea9facb43eab3c687cba99344dacfda3226 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:15:27 +0300 Subject: [PATCH 38/55] Travis-CI fix. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 60c67c8..cb14123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: - nuget install secure-file -ExcludeVersion - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" -solution: src/NGettext.sln +solution: NGettext.sln script: - - xbuild src/NGettext.sln + - xbuild NGettext.sln From dcba12554df7e76e79711a12d3e3c71820e63d84 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:25:55 +0300 Subject: [PATCH 39/55] Travis-CI fix. --- .travis.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cb14123..426e165 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,16 @@ env: install: - nuget install secure-file -ExcludeVersion - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" + - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh + - dnvm upgrade solution: NGettext.sln script: - - xbuild NGettext.sln + - dnvm list + - dnu restore + - cd src/NGettext + - dnu build + - cd ../.. + - cd test/NGettext.Tests + - dnx test From 8909153be6d398c47e555ea713fff96bfd9c1970 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:32:10 +0300 Subject: [PATCH 40/55] Travis-CI fix. --- .travis.yml | 1 + src/NGettext/project.json | 4 ++-- test/NGettext.Tests/project.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 426e165..36aea64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ install: - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh - dnvm upgrade + - dnvm install latest solution: NGettext.sln diff --git a/src/NGettext/project.json b/src/NGettext/project.json index 0949224..a0e05e4 100644 --- a/src/NGettext/project.json +++ b/src/NGettext/project.json @@ -16,11 +16,11 @@ "compilationOptions": { "languageVersion": "csharp6", - "keyFile": "..\\..\\NGettext.snk" + "keyFile": "../../NGettext.snk" }, "packInclude": { - "LICENSE": "..\\..\\LICENSE" + "LICENSE": "../../LICENSE" }, "dependencies": { diff --git a/test/NGettext.Tests/project.json b/test/NGettext.Tests/project.json index bfa0a35..164f1f0 100644 --- a/test/NGettext.Tests/project.json +++ b/test/NGettext.Tests/project.json @@ -17,7 +17,7 @@ }, "frameworks": { - "dnx46": { }, + "dnx451": { }, "dnxcore50": { "dependencies": { "System.Text.Encoding.CodePages": "4.0.1-beta-23409" From e04e3ab05b10f963a94e1666f163ca0ca898a024 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:39:52 +0300 Subject: [PATCH 41/55] Travis-CI fix. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 36aea64..a6ea9ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh - dnvm upgrade - - dnvm install latest + - dnvm install latest -r coreclr solution: NGettext.sln @@ -24,7 +24,7 @@ script: - dnvm list - dnu restore - cd src/NGettext - - dnu build + - dnu build --framework dnx451 - cd ../.. - cd test/NGettext.Tests - dnx test From 7a394739c77fea54584f7f53a9db736937e3fb03 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:44:25 +0300 Subject: [PATCH 42/55] Travis-CI fix. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a6ea9ea..a3aab12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ install: - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh - dnvm upgrade - - dnvm install latest -r coreclr solution: NGettext.sln From 79fde8669451a86996f17b8f63afc18c06c69c34 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:47:29 +0300 Subject: [PATCH 43/55] Travis-CI fix. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index a3aab12..695fbbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,10 +12,12 @@ env: - secure: "JO9BJHINLiXBe77OhScvVh25NTCSgyQdWmfHSYmemYJRXKd48JlGVX+Hg+uBD9e9JNrgihR4M+7MRD+p1DeFJa5fnlRs4sP6Urtw15/wdEoyMzfJ6IwcQgH9L00dPrjH2vXdemFQHl3v9ViUQbqNwUmANxjOHv3T2xnN7pt+IiglTRGFAPsHXSAGxlhz3XGJC9f3nrTVAr8Btwf7nAxjHutr97kvw2i83sTWvEWl26CVRb+rSu3xjoK5ze+4UXXlMNni6qkXzKnvWgYDmmrLNaU6L6GWcpkPl7bOAaPZ1833tQp0G7ZNAxCguSbCM3xfU0ujXn9szXaKD2zt2MGl/otkR3x7vSy/I2F1870zAEw9WEmVY0lsKwVv5YXASMqxc0APo1d2xAMEZYGDz7TnO/JJSGFLj/MNB7zRqrYG/rkD75V2jd3O/rXwzHQL1J9n/G9by9lq3EWYxPHZ4bF9xOCEgtD5ow27xWmcwFnF4mZNErOezwjIvmZdQXymBxM094yc/kHS30gsvS/HwzzK7Ccb04Uvqdogl9nOI2Okm85fhnkEHAK4YE+XVKxgLOLPcuSTs9qtqwe5Tte+ACkqdCeivtacWcRNInbchfbldc53VjPXZ/tRrZAm+snCkukOHF07m38JpaGuiXaBiEBvGMPbIB6vCObh3rwUnYE255Q=" install: + - apt-get install libunwind8 - nuget install secure-file -ExcludeVersion - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh - dnvm upgrade + - dnvm install latest -r coreclr solution: NGettext.sln From 85e6e0c542921ee90871e1ed8458e7ed9a072c38 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:49:50 +0300 Subject: [PATCH 44/55] Travis-CI fix. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 695fbbe..c17396c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ env: - secure: "JO9BJHINLiXBe77OhScvVh25NTCSgyQdWmfHSYmemYJRXKd48JlGVX+Hg+uBD9e9JNrgihR4M+7MRD+p1DeFJa5fnlRs4sP6Urtw15/wdEoyMzfJ6IwcQgH9L00dPrjH2vXdemFQHl3v9ViUQbqNwUmANxjOHv3T2xnN7pt+IiglTRGFAPsHXSAGxlhz3XGJC9f3nrTVAr8Btwf7nAxjHutr97kvw2i83sTWvEWl26CVRb+rSu3xjoK5ze+4UXXlMNni6qkXzKnvWgYDmmrLNaU6L6GWcpkPl7bOAaPZ1833tQp0G7ZNAxCguSbCM3xfU0ujXn9szXaKD2zt2MGl/otkR3x7vSy/I2F1870zAEw9WEmVY0lsKwVv5YXASMqxc0APo1d2xAMEZYGDz7TnO/JJSGFLj/MNB7zRqrYG/rkD75V2jd3O/rXwzHQL1J9n/G9by9lq3EWYxPHZ4bF9xOCEgtD5ow27xWmcwFnF4mZNErOezwjIvmZdQXymBxM094yc/kHS30gsvS/HwzzK7Ccb04Uvqdogl9nOI2Okm85fhnkEHAK4YE+XVKxgLOLPcuSTs9qtqwe5Tte+ACkqdCeivtacWcRNInbchfbldc53VjPXZ/tRrZAm+snCkukOHF07m38JpaGuiXaBiEBvGMPbIB6vCObh3rwUnYE255Q=" install: - - apt-get install libunwind8 + - sudo apt-get install -y libunwind8 - nuget install secure-file -ExcludeVersion - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh From b0fe283c032d71cfc57afc65105f3d3b77a444b4 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 21:59:08 +0300 Subject: [PATCH 45/55] Travis-CI fix. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c17396c..b7bbfc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,4 +28,4 @@ script: - dnu build --framework dnx451 - cd ../.. - cd test/NGettext.Tests - - dnx test + - dnx test -parallel none From e1165b08cc17b7cdee552047bc9265183fffd8ee Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 22:20:34 +0300 Subject: [PATCH 46/55] Removed coreclr backend installation from Travis-CI config. --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7bbfc1..892bf4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,12 +12,10 @@ env: - secure: "JO9BJHINLiXBe77OhScvVh25NTCSgyQdWmfHSYmemYJRXKd48JlGVX+Hg+uBD9e9JNrgihR4M+7MRD+p1DeFJa5fnlRs4sP6Urtw15/wdEoyMzfJ6IwcQgH9L00dPrjH2vXdemFQHl3v9ViUQbqNwUmANxjOHv3T2xnN7pt+IiglTRGFAPsHXSAGxlhz3XGJC9f3nrTVAr8Btwf7nAxjHutr97kvw2i83sTWvEWl26CVRb+rSu3xjoK5ze+4UXXlMNni6qkXzKnvWgYDmmrLNaU6L6GWcpkPl7bOAaPZ1833tQp0G7ZNAxCguSbCM3xfU0ujXn9szXaKD2zt2MGl/otkR3x7vSy/I2F1870zAEw9WEmVY0lsKwVv5YXASMqxc0APo1d2xAMEZYGDz7TnO/JJSGFLj/MNB7zRqrYG/rkD75V2jd3O/rXwzHQL1J9n/G9by9lq3EWYxPHZ4bF9xOCEgtD5ow27xWmcwFnF4mZNErOezwjIvmZdQXymBxM094yc/kHS30gsvS/HwzzK7Ccb04Uvqdogl9nOI2Okm85fhnkEHAK4YE+XVKxgLOLPcuSTs9qtqwe5Tte+ACkqdCeivtacWcRNInbchfbldc53VjPXZ/tRrZAm+snCkukOHF07m38JpaGuiXaBiEBvGMPbIB6vCObh3rwUnYE255Q=" install: - - sudo apt-get install -y libunwind8 - nuget install secure-file -ExcludeVersion - mono secure-file/tools/secure-file.exe -decrypt NGettext.snk.enc -secret "${SNK_SECRET}" - curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/dnvminstall.sh | sh && source ~/.dnx/dnvm/dnvm.sh - dnvm upgrade - - dnvm install latest -r coreclr solution: NGettext.sln From 67222819d2e6e5db0adfceb21a4909a20662e1d6 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 22:54:38 +0300 Subject: [PATCH 47/55] README file update. --- README.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 865dafe..25dfa01 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -NGettext [![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext) +NGettext [![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext) [![Build Status](https://ci.appveyor.com/api/projects/status/oc151pvllqqy0po9?svg=true)](https://ci.appveyor.com/project/neris/ngettext) ======== -Copyright (C) 2012,2015 Neris Ereptoris . +Copyright (C) 2012-2016 Neris Ereptoris . Just another one GNU/Gettext implementation for .NET. -Requires Microsoft .NET Framework 2.0 or higher or Mono. +Works fine on Microsoft .NET Framework version 2.0 or higher, Mono and even on .NET Core. This implementation loads translations directly from gettext *.mo files (no need to compile a satellite assembly) and can handle multiple translation domains and multiple locales in one application instance. It supports both little-endian and big-endian MO files, automatic (header-based) encoding detection. @@ -50,8 +50,8 @@ Building from the sources ### Building on Windows Requirements: - Microsoft .NET Framework 2.0 or higher, - [NAnt](http://nant.sourceforge.net/). + Microsoft Visual Studio 2015, + . Just run `build.bat` to build project with the Release configuration. @@ -60,10 +60,15 @@ Building from the sources Installation and usage ---------------------- -All you need to do is just install a [NuGet package](https://www.nuget.org/packages/NGettext/): +All you need to do is just install a [NuGet package](https://www.nuget.org/packages/NGettext/) +from the package manager console: ``` PM> Install-Package NGettext ``` +or through DNX Utility: +``` +$ dnu install NGettext +``` Alternatively you can download [compiled binaries](https://github.com/neris/NGettext/releases) or the [source code](https://github.com/neris/NGettext) and add a reference to `NGettext.dll` or `NGettext.csproj` to your project. @@ -86,6 +91,14 @@ Now you can use NGettext in your code: Console.WriteLine(catalog.GetString("Hello, {0}!", "World")); // String.Format support ``` +### .NET CoreCLR + +If you using this library under CoreCLR and you want to use encodings different from UTF-8 for your *.mo files, you need to include [System.Text.Encoding.CodePages](https://www.nuget.org/packages/System.Text.Encoding.CodePages/) package into your application and initialize it like this: +```csharp + #if DNXCORE50 + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + #endif +``` ### Culture-specific message formatting From 505ccc59f846ba7d45f12ba324aa756daf712644 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Thu, 14 Jan 2016 22:55:27 +0300 Subject: [PATCH 48/55] README file update. --- README.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/README.md b/README.md index 25dfa01..f70d01d 100644 --- a/README.md +++ b/README.md @@ -36,26 +36,6 @@ It's hard to build and maintain translation files and change locale inside your * NGettext provides nice and simple API for translation. -Building from the sources -------------------------- - -### Building on Linux - - Requirements: - [Mono](http://www.go-mono.com/mono-downloads/download.html), - [NAnt](http://nant.sourceforge.net/). - - Execute the `nant` command in the project directory to build project with the Release configuration. - -### Building on Windows - - Requirements: - Microsoft Visual Studio 2015, - . - - Just run `build.bat` to build project with the Release configuration. - - Installation and usage ---------------------- From 475d0148af9f7a04bcf7c17680b84842e1d8cc75 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 Jan 2016 18:11:23 +0300 Subject: [PATCH 49/55] Some refactorings and minor fixes. --- src/NGettext/Catalog.cs | 8 +- src/NGettext/Loaders/MoAstPluralLoader.cs | 6 +- src/NGettext/Loaders/MoFile.cs | 52 ++++ src/NGettext/Loaders/MoFileParser.cs | 100 +++----- src/NGettext/Loaders/MoLoader.cs | 109 +++++++-- .../Plural/DefaultPluralRuleGenerator.cs | 2 +- src/NGettext/Plural/IPluralRuleTextParser.cs | 2 +- test/NGettext.Tests/BaseCatalogTest.cs | 227 ------------------ test/NGettext.Tests/CatalogFileLoadingTest.cs | 57 +++++ test/NGettext.Tests/CatalogTest.cs | 219 +++++++++++++++-- .../Loaders/MoFileParserTest.cs | 26 +- test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs | 14 -- 12 files changed, 456 insertions(+), 366 deletions(-) create mode 100644 src/NGettext/Loaders/MoFile.cs delete mode 100644 test/NGettext.Tests/BaseCatalogTest.cs create mode 100644 test/NGettext.Tests/CatalogFileLoadingTest.cs delete mode 100644 test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs diff --git a/src/NGettext/Catalog.cs b/src/NGettext/Catalog.cs index dc00828..302cd2b 100644 --- a/src/NGettext/Catalog.cs +++ b/src/NGettext/Catalog.cs @@ -49,7 +49,7 @@ public IPluralRule PluralRule ///

    /// Initializes a new instance of the class that has no translations - /// using the current UI culture info and default plural rule. + /// using the current UI culture info and plural rule generated by DefaultPluralRuleGenerator for the current UI culture. /// public Catalog() : this(CultureInfo.CurrentUICulture) @@ -58,14 +58,14 @@ public Catalog() /// /// Initializes a new instance of the class that has no translations - /// using given culture info and default plural rule. + /// using given culture info and plural rule generated by DefaultPluralRuleGenerator for given culture. /// /// Culture info. public Catalog(CultureInfo cultureInfo) { this.CultureInfo = cultureInfo; this.Translations = new Dictionary(); - this.PluralRule = Plural.PluralRule.Default; + this.PluralRule = (new DefaultPluralRuleGenerator()).CreateRule(cultureInfo); } /// @@ -93,7 +93,7 @@ public Catalog(ILoader loader, CultureInfo cultureInfo) } catch (FileNotFoundException exception) { - // Supress FileNotFound exceptions + // Suppress FileNotFound exceptions Trace.WriteLine(String.Format("Translation file loading fail: {0}", exception.Message), "NGettext"); } } diff --git a/src/NGettext/Loaders/MoAstPluralLoader.cs b/src/NGettext/Loaders/MoAstPluralLoader.cs index 0c5f06a..a2ac774 100644 --- a/src/NGettext/Loaders/MoAstPluralLoader.cs +++ b/src/NGettext/Loaders/MoAstPluralLoader.cs @@ -55,7 +55,7 @@ public MoAstPluralLoader(Stream moStream, MoFileParser parser) /// /// public MoAstPluralLoader(string domain, string localeDir) - : base(domain, localeDir, new AstPluralRuleGenerator(), new MoFileParser()) + : base(domain, localeDir, new AstPluralRuleGenerator()) { } @@ -66,7 +66,7 @@ public MoAstPluralLoader(string domain, string localeDir) /// /// public MoAstPluralLoader(string filePath) - : base(filePath, new AstPluralRuleGenerator(), new MoFileParser()) + : base(filePath, new AstPluralRuleGenerator()) { } @@ -77,7 +77,7 @@ public MoAstPluralLoader(string filePath) ///
  • /// public MoAstPluralLoader(Stream moStream) - : base(moStream, new AstPluralRuleGenerator(), new MoFileParser()) + : base(moStream, new AstPluralRuleGenerator()) { } } diff --git a/src/NGettext/Loaders/MoFile.cs b/src/NGettext/Loaders/MoFile.cs new file mode 100644 index 0000000..71099f9 --- /dev/null +++ b/src/NGettext/Loaders/MoFile.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NGettext.Loaders +{ + /// + /// Represents a parsed MO file data. + /// + public class MoFile + { + /// + /// Gets parsed file's format revision. + /// + public Version FormatRevision { get; protected set; } + + /// + /// Gets a value that indicates whenever loaded file was in the BigEndian format. + /// + public bool BigEndian { get; protected set; } + + /// + /// Gets or sets file's encoding. + /// + public Encoding Encoding { get; set; } + + /// + /// Gets parsed file's meta data. + /// + public Dictionary Headers { get; protected set; } + + /// + /// Gets parsed file's translation strings. + /// + public Dictionary Translations { get; protected set; } + + /// + /// Initializes a new instance of the class. + /// + /// File format revision. + /// File encoding. + /// File endianness. + public MoFile(Version formatRevision, Encoding encoding = null, bool bigEndian = false) + { + this.FormatRevision = formatRevision; + this.BigEndian = bigEndian; + this.Encoding = encoding; + this.Headers = new Dictionary(StringComparer.OrdinalIgnoreCase); + this.Translations = new Dictionary(); + } + } +} diff --git a/src/NGettext/Loaders/MoFileParser.cs b/src/NGettext/Loaders/MoFileParser.cs index d9075ce..5e597cf 100644 --- a/src/NGettext/Loaders/MoFileParser.cs +++ b/src/NGettext/Loaders/MoFileParser.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; -using System.Text.RegularExpressions; namespace NGettext.Loaders { @@ -27,48 +25,35 @@ private struct StringOffsetTable } /// - /// Current encoding for decoding all strings in given MO file. + /// Default encoding for decoding all strings in given MO file. + /// Must be binary compatible with US-ASCII to be able to read file headers. /// /// - /// Default value is UTF-8 as it is compatible with required by specifications us-ascii. - /// This value could be changed when DetectEncoding property is set to True and the MO file - /// contains a valid charset name in the Content-Type header. + /// Default value is UTF-8 as it is compatible with required by specifications US-ASCII. /// - public Encoding Encoding { get; set; } + public Encoding DefaultEncoding { get; set; } /// /// Gets or sets a value that indicates whenever the parser can detect file encoding using the Content-Type MIME header. /// - public bool DetectEncoding { get; set; } + public bool AutoDetectEncoding { get; set; } /// - /// Gets a value that indicates whenever loaded file was in the big-endian format. + /// Initializes a new instance of the class with UTF-8 as default encoding and with enabled automatic encoding detection. /// - public bool IsBigEndian { get; protected set; } - - /// - /// Gets parsed file's format revision. - /// - public Version FormatRevision { get; protected set; } - - /// - /// Gets parsed file's metadata. - /// - public Dictionary Headers { get; protected set; } - - /// - /// Gets parsed file's translation strings. - /// - public Dictionary Translations { get; protected set; } + public MoFileParser() + { + this.DefaultEncoding = Encoding.UTF8; + this.AutoDetectEncoding = true; + } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class using given default encoding and given automatic encoding detection option. /// - public MoFileParser() + public MoFileParser(Encoding defaultEncoding, bool autoDetectEncoding = true) { - this.Encoding = Encoding.UTF8; - this.DetectEncoding = true; - this._Init(); + this.DefaultEncoding = defaultEncoding; + this.AutoDetectEncoding = autoDetectEncoding; } /// @@ -78,9 +63,9 @@ public MoFileParser() /// http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html /// /// Stream that contain binary data in the MO file format - public void Parse(Stream stream) + /// Parsed file data. + public MoFile Parse(Stream stream) { - this._Init(); Trace.WriteLine("Trying to parse a MO file stream...", "NGettext"); if (stream == null || stream.Length < 20) @@ -88,18 +73,19 @@ public void Parse(Stream stream) throw new ArgumentException("Stream can not be null of less than 20 bytes long."); } + var bigEndian = false; var reader = new BinaryReader(new ReadOnlyStreamWrapper(stream)); try { var magicNumber = reader.ReadUInt32(); if (magicNumber != MO_FILE_MAGIC) { - // System.IO.BinaryReader does not respect machine endianness and always uses little-endian - // So we need to detect and read big-endian files by ourselves + // System.IO.BinaryReader does not respect machine endianness and always uses LittleEndian + // So we need to detect and read BigEendian files by ourselves if (_ReverseBytes(magicNumber) == MO_FILE_MAGIC) { - Trace.WriteLine("Big Endian file detected. Switching readers...", "NGettext"); - this.IsBigEndian = true; + Trace.WriteLine("BigEndian file detected. Switching readers...", "NGettext"); + bigEndian = true; ((IDisposable)reader).Dispose(); reader = new BigEndianBinaryReader(new ReadOnlyStreamWrapper(stream)); } @@ -110,13 +96,13 @@ public void Parse(Stream stream) } var revision = reader.ReadInt32(); - this.FormatRevision = new Version(revision >> 16, revision & 0xffff); + var parsedFile = new MoFile(new Version(revision >> 16, revision & 0xffff), this.DefaultEncoding, bigEndian); - Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", this.FormatRevision.Major, this.FormatRevision.Minor), "NGettext"); + Trace.WriteLine(String.Format("MO File Revision: {0}.{1}.", parsedFile.FormatRevision.Major, parsedFile.FormatRevision.Minor), "NGettext"); - if (this.FormatRevision.Major > MAX_SUPPORTED_VERSION) + if (parsedFile.FormatRevision.Major > MAX_SUPPORTED_VERSION) { - throw new Exception(String.Format("Unsupported MO file major revision: {0}.", this.FormatRevision.Major)); + throw new Exception(String.Format("Unsupported MO file major revision: {0}.", parsedFile.FormatRevision.Major)); } var stringCount = reader.ReadInt32(); @@ -130,7 +116,7 @@ public void Parse(Stream stream) var originalTable = new StringOffsetTable[stringCount]; var translationTable = new StringOffsetTable[stringCount]; - Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", this.Encoding), "NGettext"); + Trace.WriteLine(String.Format("Trying to parse strings using encoding \"{0}\"...", parsedFile.Encoding), "NGettext"); reader.BaseStream.Seek(originalTableOffset, SeekOrigin.Begin); for (int i = 0; i < stringCount; i++) @@ -149,32 +135,32 @@ public void Parse(Stream stream) for (int i = 0; i < stringCount; i++) { - var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length); - var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length); + var originalStrings = this._ReadStrings(reader, originalTable[i].Offset, originalTable[i].Length, parsedFile.Encoding); + var translatedStrings = this._ReadStrings(reader, translationTable[i].Offset, translationTable[i].Length, parsedFile.Encoding); if (originalStrings.Length == 0 || translatedStrings.Length == 0) continue; if (originalStrings[0].Length == 0) { - // MO file metadata processing + // MO file meta data processing foreach (var headerText in translatedStrings[0].Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)) { var header = headerText.Split(new[] { ':' }, 2); if (header.Length == 2) { - this.Headers.Add(header[0], header[1].Trim()); + parsedFile.Headers.Add(header[0], header[1].Trim()); } } - if (this.DetectEncoding && this.Headers.ContainsKey("Content-Type")) + if (this.AutoDetectEncoding && parsedFile.Headers.ContainsKey("Content-Type")) { try { - var contentType = new ContentType(this.Headers["Content-Type"]); + var contentType = new ContentType(parsedFile.Headers["Content-Type"]); if (!String.IsNullOrEmpty(contentType.CharSet)) { - this.Encoding = Encoding.GetEncoding(contentType.CharSet); - Trace.WriteLine(String.Format("File encoding switched to \"{0}\" (\"{1}\" requested).", this.Encoding, contentType.CharSet), "NGettext"); + parsedFile.Encoding = Encoding.GetEncoding(contentType.CharSet); + Trace.WriteLine(String.Format("File encoding switched to \"{0}\" (\"{1}\" requested).", parsedFile.Encoding, contentType.CharSet), "NGettext"); } } catch (Exception exception) @@ -184,11 +170,11 @@ public void Parse(Stream stream) } } - this.Translations.Add(originalStrings[0], translatedStrings); + parsedFile.Translations.Add(originalStrings[0], translatedStrings); } Trace.WriteLine("String parsing completed.", "NGettext"); - + return parsedFile; } finally { @@ -196,19 +182,11 @@ public void Parse(Stream stream) } } - private void _Init() - { - this.Headers = new Dictionary(StringComparer.OrdinalIgnoreCase); - this.Translations = new Dictionary(); - this.FormatRevision = null; - this.IsBigEndian = false; - } - - private string[] _ReadStrings(BinaryReader reader, int offset, int length) + private string[] _ReadStrings(BinaryReader reader, int offset, int length, Encoding encoding) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); var stringBytes = reader.ReadBytes(length); - return this.Encoding.GetString(stringBytes, 0, stringBytes.Length).Split('\0'); + return encoding.GetString(stringBytes, 0, stringBytes.Length).Split('\0'); } private static uint _ReverseBytes(uint value) diff --git a/src/NGettext/Loaders/MoLoader.cs b/src/NGettext/Loaders/MoLoader.cs index 6ce41d0..6bf2b6d 100644 --- a/src/NGettext/Loaders/MoLoader.cs +++ b/src/NGettext/Loaders/MoLoader.cs @@ -11,6 +11,9 @@ namespace NGettext.Loaders /// public class MoLoader : ILoader { + private const string LC_MESSAGES = "LC_MESSAGES"; + private const string MO_FILE_EXT = ".mo"; + private readonly Stream _MoStream; private readonly string _FilePath; private readonly string _Domain; @@ -26,8 +29,10 @@ public class MoLoader : ILoader /// public MoFileParser Parser { get; private set; } + #region Constructors + /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file /// that will be located in the localeDir using the domain name and catalog's culture info. /// /// @@ -52,7 +57,7 @@ public MoLoader(string domain, string localeDir, IPluralRuleGenerator pluralRule } /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file /// from the specified path. /// /// @@ -73,7 +78,7 @@ public MoLoader(string filePath, IPluralRuleGenerator pluralRuleGenerator, MoFil } /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file /// from the specified stream. /// /// @@ -93,8 +98,36 @@ public MoLoader(Stream moStream, IPluralRuleGenerator pluralRuleGenerator, MoFil this.Parser = parser; } + #endregion + + #region Constructor overloads + + /// + /// Initializes a new instance of the class which will try to load a MO file + /// that will be located in the localeDir using the domain name and catalog's culture info. + /// + /// + /// + /// + public MoLoader(string domain, string localeDir, IPluralRuleGenerator pluralRuleGenerator) + : this(domain, localeDir, pluralRuleGenerator, new MoFileParser()) + { + } + + /// + /// Initializes a new instance of the class which will try to load a MO file + /// that will be located in the localeDir using the domain name and catalog's culture info. + /// + /// + /// + /// + public MoLoader(string domain, string localeDir, MoFileParser parser) + : this(domain, localeDir, new DefaultPluralRuleGenerator(), parser) + { + } + /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file /// that will be located in the localeDir using the domain name and catalog's culture info. /// /// @@ -105,7 +138,29 @@ public MoLoader(string domain, string localeDir) } /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file + /// from the specified path. + /// + /// + /// + public MoLoader(string filePath, IPluralRuleGenerator pluralRuleGenerator) + : this(filePath, pluralRuleGenerator, new MoFileParser()) + { + } + + /// + /// Initializes a new instance of the class which will try to load a MO file + /// from the specified path. + /// + /// + public MoLoader(string filePath, MoFileParser parser) + : this(filePath, new DefaultPluralRuleGenerator(), parser) + { + } + + /// + /// Initializes a new instance of the class which will try to load a MO file /// from the specified path. /// /// @@ -115,7 +170,29 @@ public MoLoader(string filePath) } /// - /// Initializes a new instance of the class whitch will try to load a MO file + /// Initializes a new instance of the class which will try to load a MO file + /// from the specified stream. + /// + /// + /// + public MoLoader(Stream moStream, IPluralRuleGenerator pluralRuleGenerator) + : this(moStream, pluralRuleGenerator, new MoFileParser()) + { + } + + /// + /// Initializes a new instance of the class which will try to load a MO file + /// from the specified stream. + /// + /// + /// + public MoLoader(Stream moStream, MoFileParser parser) + : this(moStream, new DefaultPluralRuleGenerator(), parser) + { + } + + /// + /// Initializes a new instance of the class which will try to load a MO file /// from the specified stream. /// /// @@ -124,6 +201,8 @@ public MoLoader(Stream moStream) { } + #endregion + /// /// Loads translations to the specified catalog using catalog's culture info. @@ -183,30 +262,29 @@ protected virtual void Load(string filePath, Catalog catalog) /// protected virtual void Load(Stream moStream, Catalog catalog) { - var parser = this.Parser; - parser.Parse(moStream); + var parsedMoFile = this.Parser.Parse(moStream); - this.Load(parser, catalog); + this.Load(parsedMoFile, catalog); } /// /// Loads translations to the specified catalog using specified MO file parser. /// - /// + /// /// - protected virtual void Load(MoFileParser parser, Catalog catalog) + protected virtual void Load(MoFile parsedMoFile, Catalog catalog) { - foreach (var translation in parser.Translations) + foreach (var translation in parsedMoFile.Translations) { catalog.Translations.Add(translation.Key, translation.Value); } - if (parser.Headers.ContainsKey("Plural-Forms")) + if (parsedMoFile.Headers.ContainsKey("Plural-Forms")) { var generator = this.PluralRuleGenerator as IPluralRuleTextParser; if (generator != null) { - generator.SetPluralRuleText(parser.Headers["Plural-Forms"]); + generator.SetPluralRuleText(parsedMoFile.Headers["Plural-Forms"]); } } catalog.PluralRule = this.PluralRuleGenerator.CreateRule(catalog.CultureInfo); @@ -222,6 +300,7 @@ protected virtual void Load(MoFileParser parser, Catalog catalog) protected virtual string FindTranslationFile(CultureInfo cultureInfo, string domain, string localeDir) { var possibleFiles = new[] { + this.GetFileName(localeDir, domain, cultureInfo.Name.Replace('-', '_')), this.GetFileName(localeDir, domain, cultureInfo.Name), this.GetFileName(localeDir, domain, cultureInfo.TwoLetterISOLanguageName) }; @@ -247,7 +326,7 @@ protected virtual string FindTranslationFile(CultureInfo cultureInfo, string dom /// protected virtual string GetFileName(string localeDir, string domain, string locale) { - return Path.Combine(localeDir, Path.Combine(locale.Replace('-', '_'), Path.Combine("LC_MESSAGES", domain + ".mo"))); + return Path.Combine(localeDir, Path.Combine(locale, Path.Combine(LC_MESSAGES, domain + MO_FILE_EXT))); } } } \ No newline at end of file diff --git a/src/NGettext/Plural/DefaultPluralRuleGenerator.cs b/src/NGettext/Plural/DefaultPluralRuleGenerator.cs index 13feafe..f742222 100644 --- a/src/NGettext/Plural/DefaultPluralRuleGenerator.cs +++ b/src/NGettext/Plural/DefaultPluralRuleGenerator.cs @@ -235,7 +235,7 @@ public virtual IPluralRule CreateRule(CultureInfo cultureInfo) case "gd": return new PluralRule(4, number => ((number == 1) || (number == 11)) ? 0 : (((number == 2) || (number == 12)) ? 1 : (((((number >= 3) && (number <= 10)) || ((number >= 13) && (number <= 19))) ? 2 : 3)))); } - return new PluralRule(1, number => 0); + return PluralRule.Default; } } } \ No newline at end of file diff --git a/src/NGettext/Plural/IPluralRuleTextParser.cs b/src/NGettext/Plural/IPluralRuleTextParser.cs index 49603a2..c7aa0ff 100644 --- a/src/NGettext/Plural/IPluralRuleTextParser.cs +++ b/src/NGettext/Plural/IPluralRuleTextParser.cs @@ -5,7 +5,7 @@ namespace NGettext.Plural /// /// Represents a plural rule generator that can generate plural rules based on parsed text. /// - public interface IPluralRuleTextParser + public interface IPluralRuleTextParser : IPluralRuleGenerator { /// /// Sets a plural rule text representation that needs to be parsed. diff --git a/test/NGettext.Tests/BaseCatalogTest.cs b/test/NGettext.Tests/BaseCatalogTest.cs deleted file mode 100644 index f9c0112..0000000 --- a/test/NGettext.Tests/BaseCatalogTest.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System.Globalization; -using Xunit; -using NGettext.Tests.Stabs; - -namespace NGettext.Tests -{ - public class BaseCatalogTest - { - - #region GetString - - [Fact] - public void TestGetString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("key2", new[] { "value2" }); - t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - t.Translations.Add("", new[] { "emptyIdValue" }); - - Assert.Equal("value1", t.GetString("key1")); - Assert.Equal("value2", t.GetString("key2")); - Assert.Equal("value3plural1", t.GetString("key3")); - Assert.Equal("notFoundKey2", t.GetString("notFoundKey2")); - Assert.Equal("", t.GetString("")); - } - - [Fact] - public void TestGetStringFormat() - { - var t = new EmptyBaseCatalog(); - - Assert.Equal("Foo bar", t.GetString("Foo {0}", "bar")); - Assert.Equal("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); - Assert.Equal("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); - } - - [Fact] - public void TestGetStringFormatCulture() - { - var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); - var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - - Assert.Equal("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); - Assert.Equal("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); - } - - #endregion - - #region GetPluralString - - [Fact] - public void TestGetPluralString() - { - var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - t.Translations.Add("key1", new[] {"value1"}); - t.Translations.Add("key2plural1", new[] {"value2plural1", "value2plural2"}); - - Assert.Equal("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); - Assert.Equal("value1", t.GetPluralString("key1", "key1", 1)); - Assert.Equal("key1plural", t.GetPluralString("key1", "key1plural", 2)); - - Assert.Equal("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); - Assert.Equal("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); - } - - [Fact] - public void TestGetPluralStringFormat() - { - var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - - Assert.Equal("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.Equal("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.Equal("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); - - Assert.Equal("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); - Assert.Equal("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); - Assert.Equal("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); - } - - [Fact] - public void TestGetPluralStringInternational() - { - var t = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - t.Translations.Add("You have {0} apple", new[] { "У Вас {0} яблоко", "У Вас {0} яблока", "У Вас {0} яблок" }); - - Assert.Equal("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); - Assert.Equal("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); - Assert.Equal("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); - Assert.Equal("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); - Assert.Equal("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); - Assert.Equal("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); - Assert.Equal("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); - Assert.Equal("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); - - Assert.Equal("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); - } - - [Fact] - public void TestGetPluralStringFormatCulture() - { - var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); - var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - - Assert.Equal("Foo 1.23", catalogEn.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); - Assert.Equal("Foo 1,23", catalogRu.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); - } - - #endregion - - #region GetParticularString - - [Fact] - public void TestGetParticularString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1", new[] { "value3" }); - - Assert.Equal("value1", t.GetString("key1")); - Assert.Equal("value2", t.GetParticularString("context1", "key1")); - Assert.Equal("value3", t.GetParticularString("context2", "key1")); - Assert.Equal("key1", t.GetParticularString("context3", "key1")); - } - - [Fact] - public void TestGetParticularStringFormat() - { - var t = new EmptyBaseCatalog(); - - Assert.Equal("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); - Assert.Equal("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); - } - - [Fact] - public void TestGetParticularStringFormatCulture() - { - var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); - var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - - Assert.Equal("Foo 1.23", catalogEn.GetParticularString("context", "Foo {0}", 1.23)); - Assert.Equal("Foo 1,23", catalogRu.GetParticularString("context", "Foo {0}", 1.23)); - } - - #endregion - - #region GetParticularPluralString - - [Fact] - public void TestGetParticularPluralString() - { - var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - t.Translations.Add("context1" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); - t.Translations.Add("context2" + BaseCatalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); - - Assert.Equal("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); - Assert.Equal("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); - Assert.Equal("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); - Assert.Equal("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); - } - - [Fact] - public void TestGetParticularPluralStringFormat() - { - var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - - Assert.Equal("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); - Assert.Equal("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); - Assert.Equal("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); - Assert.Equal("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); - } - - [Fact] - public void TestGetParticularPluralStringFormatCulture() - { - var catalogEn = new EmptyBaseCatalog(new CultureInfo("en-US")); - var catalogRu = new EmptyBaseCatalog(new CultureInfo("ru-RU")); - - Assert.Equal("Foo 1.23", catalogEn.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); - Assert.Equal("Foo 1,23", catalogRu.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); - } - - #endregion - - #region *Default methods - - [Fact] - public void TestProtectedGetString() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - - Assert.Equal("value1", t.GetStringDefault("key1", null)); - Assert.Equal(null, t.GetStringDefault("key2", null)); - Assert.Equal("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); - } - - [Fact] - public void TestProtectedGetPluralString() - { - var t = new EmptyBaseCatalog(new CultureInfo("en-US")); - t.Translations.Add("key1", new[] { "value1" }); - - Assert.Equal("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); - Assert.Equal("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); - Assert.Equal("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); - Assert.Equal("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); - } - - [Fact] - public void TestProtectedGetTranslations() - { - var t = new EmptyBaseCatalog(); - t.Translations.Add("key1", new[] { "value1" }); - t.Translations.Add("key2", new[] { "value2" }); - t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - - Assert.Equal(new[] { "value1" }, t.GetTranslations("key1")); - Assert.Equal(new[] { "value2" }, t.GetTranslations("key2")); - Assert.Equal(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); - Assert.Equal(null, t.GetTranslations("key4")); - } - - #endregion - } -} \ No newline at end of file diff --git a/test/NGettext.Tests/CatalogFileLoadingTest.cs b/test/NGettext.Tests/CatalogFileLoadingTest.cs new file mode 100644 index 0000000..dcb13a2 --- /dev/null +++ b/test/NGettext.Tests/CatalogFileLoadingTest.cs @@ -0,0 +1,57 @@ +using System.Globalization; +using System.IO; +using Xunit; + +namespace NGettext.Tests +{ + public class CatalogFileLoadingTest + { + public string LocalesDir; + + public CatalogFileLoadingTest() + { + this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); + } + + [Fact] + public void TestEmpty() + { + var t = new Catalog(); + + Assert.Equal(0, t.Translations.Count); + Assert.Equal(CultureInfo.CurrentUICulture, t.CultureInfo); + + t = new Catalog(new CultureInfo("fr")); + Assert.Equal(new CultureInfo("fr"), t.CultureInfo); + } + + [Fact] + public void TestStream() + { + using (var stream = File.OpenRead(Path.Combine(this.LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) + { + var t = new Catalog(stream, new CultureInfo("ru-RU")); + this._TestLoadedTranslation(t); + } + } + + [Fact] + public void TestLocaleDir() + { + var t = new Catalog("Test", this.LocalesDir, new CultureInfo("ru-RU")); + this._TestLoadedTranslation(t); + } + + private void _TestLoadedTranslation(ICatalog t) + { + Assert.Equal("тест", t.GetString("test")); + Assert.Equal("тест2", t.GetString("test2")); + Assert.Equal("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); + Assert.Equal("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); + + Assert.Equal("тест3контекст1", t.GetParticularString("context1", "test3")); + Assert.Equal("тест3контекст2", t.GetParticularString("context2", "test3")); + } + + } +} \ No newline at end of file diff --git a/test/NGettext.Tests/CatalogTest.cs b/test/NGettext.Tests/CatalogTest.cs index c4bbff4..0efc6d4 100644 --- a/test/NGettext.Tests/CatalogTest.cs +++ b/test/NGettext.Tests/CatalogTest.cs @@ -1,57 +1,226 @@ using System.Globalization; -using System.IO; using Xunit; namespace NGettext.Tests { public class CatalogTest { - public string LocalesDir; - public CatalogTest() + #region GetString + + [Fact] + public void TestGetString() + { + var t = new Catalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("key2", new[] { "value2" }); + t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); + t.Translations.Add("", new[] { "emptyIdValue" }); + + Assert.Equal("value1", t.GetString("key1")); + Assert.Equal("value2", t.GetString("key2")); + Assert.Equal("value3plural1", t.GetString("key3")); + Assert.Equal("notFoundKey2", t.GetString("notFoundKey2")); + Assert.Equal("", t.GetString("")); + } + + [Fact] + public void TestGetStringFormat() + { + var t = new Catalog(); + + Assert.Equal("Foo bar", t.GetString("Foo {0}", "bar")); + Assert.Equal("Foo bar baz", t.GetString("Foo {0} {1}", "bar", "baz")); + Assert.Equal("Foo 1 2", t.GetString("Foo {0} {1}", 1, 2)); + } + + [Fact] + public void TestGetStringFormatCulture() + { + var catalogEn = new Catalog(new CultureInfo("en-US")); + var catalogRu = new Catalog(new CultureInfo("ru-RU")); + + Assert.Equal("Foo 1.23", catalogEn.GetString("Foo {0}", 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetString("Foo {0}", 1.23)); + } + + #endregion + + #region GetPluralString + + [Fact] + public void TestGetPluralString() + { + var t = new Catalog(new CultureInfo("en-US")); + t.Translations.Add("key1", new[] {"value1"}); + t.Translations.Add("key2plural1", new[] {"value2plural1", "value2plural2"}); + + Assert.Equal("value2plural1", t.GetPluralString("key2plural1", "key2plural2", 1)); + Assert.Equal("value1", t.GetPluralString("key1", "key1", 1)); + Assert.Equal("key1plural", t.GetPluralString("key1", "key1plural", 2)); + + Assert.Equal("key3singular", t.GetPluralString("key3singular", "key3plural", 1)); + Assert.Equal("key3plural", t.GetPluralString("key3singular", "key3plural", 2)); + } + + [Fact] + public void TestGetPluralStringFormat() + { + var t = new Catalog(new CultureInfo("en-US")); + + Assert.Equal("You have 1 apple", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.Equal("You have 2 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.Equal("You have 0 apples", t.GetPluralString("You have {0} apple", "You have {0} apples", 0, 0)); + + Assert.Equal("You have 1 apple", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 1, "You", 1)); + Assert.Equal("You have 2 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 2, "You", 2)); + Assert.Equal("You have 0 apples", t.GetPluralString("{0} have {1} apple", "{0} have {1} apples", 0, "You", 0)); + } + + [Fact] + public void TestGetPluralStringInternational() + { + var t = new Catalog(new CultureInfo("ru-RU")); + t.Translations.Add("You have {0} apple", new[] { "У Вас {0} яблоко", "У Вас {0} яблока", "У Вас {0} яблок" }); + + Assert.Equal("У Вас 1 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 1, 1)); + Assert.Equal("У Вас 2 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 2, 2)); + Assert.Equal("У Вас 3 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 3, 3)); + Assert.Equal("У Вас 4 яблока", t.GetPluralString("You have {0} apple", "You have {0} apples", 4, 4)); + Assert.Equal("У Вас 5 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 5, 5)); + Assert.Equal("У Вас 6 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 6, 6)); + Assert.Equal("У Вас 11 яблок", t.GetPluralString("You have {0} apple", "You have {0} apples", 11, 11)); + Assert.Equal("У Вас 21 яблоко", t.GetPluralString("You have {0} apple", "You have {0} apples", 21, 21)); + + Assert.Equal("He has 5 apples", t.GetPluralString("He has {0} apple", "He has {0} apples", 5, 5)); + } + + [Fact] + public void TestGetPluralStringFormatCulture() + { + var catalogEn = new Catalog(new CultureInfo("en-US")); + var catalogRu = new Catalog(new CultureInfo("ru-RU")); + + Assert.Equal("Foo 1.23", catalogEn.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetPluralString("Foo {0}", "Foo {0}", (long)1.23, 1.23)); + } + + #endregion + + #region GetParticularString + + [Fact] + public void TestGetParticularString() { - this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); + var t = new Catalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("context1" + Catalog.CONTEXT_GLUE + "key1", new[] { "value2" }); + t.Translations.Add("context2" + Catalog.CONTEXT_GLUE + "key1", new[] { "value3" }); + + Assert.Equal("value1", t.GetString("key1")); + Assert.Equal("value2", t.GetParticularString("context1", "key1")); + Assert.Equal("value3", t.GetParticularString("context2", "key1")); + Assert.Equal("key1", t.GetParticularString("context3", "key1")); } [Fact] - public void TestEmpty() + public void TestGetParticularStringFormat() { var t = new Catalog(); - Assert.Equal(0, t.Translations.Count); - Assert.Equal(CultureInfo.CurrentUICulture, t.CultureInfo); + Assert.Equal("Foo bar", t.GetParticularString("context", "Foo {0}", "bar")); + Assert.Equal("Foo bar baz", t.GetParticularString("context", "Foo {0} {1}", "bar", "baz")); + } + + [Fact] + public void TestGetParticularStringFormatCulture() + { + var catalogEn = new Catalog(new CultureInfo("en-US")); + var catalogRu = new Catalog(new CultureInfo("ru-RU")); + + Assert.Equal("Foo 1.23", catalogEn.GetParticularString("context", "Foo {0}", 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetParticularString("context", "Foo {0}", 1.23)); + } + + #endregion + + #region GetParticularPluralString + + [Fact] + public void TestGetParticularPluralString() + { + var t = new Catalog(new CultureInfo("en-US")); + t.Translations.Add("context1" + Catalog.CONTEXT_GLUE + "key1-1", new[] { "value1-1", "value1-2" }); + t.Translations.Add("context2" + Catalog.CONTEXT_GLUE + "key1-1", new[] { "value2-1", "value2-2" }); - t = new Catalog(new CultureInfo("fr")); - Assert.Equal(new CultureInfo("fr"), t.CultureInfo); + Assert.Equal("value1-1", t.GetParticularPluralString("context1", "key1-1", "key1-2", 1)); + Assert.Equal("value1-2", t.GetParticularPluralString("context1", "key1-1", "key1-2", 2)); + Assert.Equal("value2-1", t.GetParticularPluralString("context2", "key1-1", "key1-2", 1)); + Assert.Equal("key1-1", t.GetParticularPluralString("context3", "key1-1", "key1-2", 1)); } [Fact] - public void TestStream() + public void TestGetParticularPluralStringFormat() { - using (var stream = File.OpenRead(Path.Combine(this.LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) - { - var t = new Catalog(stream, new CultureInfo("ru-RU")); - this._TestLoadedTranslation(t); - } + var t = new Catalog(new CultureInfo("en-US")); + + Assert.Equal("Foo bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 1, "bar")); + Assert.Equal("Bar bar", t.GetParticularPluralString("context", "Foo {0}", "Bar {0}", 2, "bar")); + Assert.Equal("Foo bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 1, "bar", "baz")); + Assert.Equal("Bar bar baz", t.GetParticularPluralString("context", "Foo {0} {1}", "Bar {0} {1}", 2, "bar", "baz")); } [Fact] - public void TestLocaleDir() + public void TestGetParticularPluralStringFormatCulture() { - var t = new Catalog("Test", this.LocalesDir, new CultureInfo("ru-RU")); - this._TestLoadedTranslation(t); + var catalogEn = new Catalog(new CultureInfo("en-US")); + var catalogRu = new Catalog(new CultureInfo("ru-RU")); + + Assert.Equal("Foo 1.23", catalogEn.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); + Assert.Equal("Foo 1,23", catalogRu.GetParticularPluralString("context", "Foo {0}", "Foo {0}", (long)1.23, 1.23)); } - private void _TestLoadedTranslation(ICatalog t) + #endregion + + #region *Default methods + + [Fact] + public void TestProtectedGetString() { - Assert.Equal("тест", t.GetString("test")); - Assert.Equal("тест2", t.GetString("test2")); - Assert.Equal("1 минута", t.GetPluralString("{0} minute", "{0} minutes", 1, 1)); - Assert.Equal("5 минут", t.GetPluralString("{0} minute", "{0} minutes", 5, 5)); + var t = new Catalog(); + t.Translations.Add("key1", new[] { "value1" }); + + Assert.Equal("value1", t.GetStringDefault("key1", null)); + Assert.Equal(null, t.GetStringDefault("key2", null)); + Assert.Equal("defaultMessage", t.GetStringDefault("key2", "defaultMessage")); + } + + [Fact] + public void TestProtectedGetPluralString() + { + var t = new Catalog(new CultureInfo("en-US")); + t.Translations.Add("key1", new[] { "value1" }); + + Assert.Equal("value1", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 1)); + Assert.Equal("defaultPlural", t.GetPluralStringDefault("key1", "defaultSingular", "defaultPlural", 2)); + Assert.Equal("defaultSingular", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 1)); + Assert.Equal("defaultPlural", t.GetPluralStringDefault("key2", "defaultSingular", "defaultPlural", 2)); + } + + [Fact] + public void TestProtectedGetTranslations() + { + var t = new Catalog(); + t.Translations.Add("key1", new[] { "value1" }); + t.Translations.Add("key2", new[] { "value2" }); + t.Translations.Add("key3", new[] { "value3plural1", "value3plural2" }); - Assert.Equal("тест3контекст1", t.GetParticularString("context1", "test3")); - Assert.Equal("тест3контекст2", t.GetParticularString("context2", "test3")); + Assert.Equal(new[] { "value1" }, t.GetTranslations("key1")); + Assert.Equal(new[] { "value2" }, t.GetTranslations("key2")); + Assert.Equal(new[] { "value3plural1", "value3plural2" }, t.GetTranslations("key3")); + Assert.Equal(null, t.GetTranslations("key4")); } + #endregion } } \ No newline at end of file diff --git a/test/NGettext.Tests/Loaders/MoFileParserTest.cs b/test/NGettext.Tests/Loaders/MoFileParserTest.cs index 14a9974..8228781 100644 --- a/test/NGettext.Tests/Loaders/MoFileParserTest.cs +++ b/test/NGettext.Tests/Loaders/MoFileParserTest.cs @@ -24,8 +24,8 @@ public void TestParsing() using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) { var parser = new MoFileParser(); - parser.Parse(stream); - this._TestLoadedTranslation(parser.Translations); + var parsedFile = parser.Parse(stream); + this._TestLoadedTranslation(parsedFile.Translations); } } @@ -35,8 +35,8 @@ public void TestBigEndianParsing() using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_BigEndian.mo"))))) { var parser = new MoFileParser(); - parser.Parse(stream); - this._TestLoadedTranslation(parser.Translations); + var parsedFile = parser.Parse(stream); + this._TestLoadedTranslation(parsedFile.Translations); } } @@ -46,8 +46,8 @@ public void TestAutoEncoding() using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_KOI8-R.mo"))))) { var parser = new MoFileParser(); - parser.Parse(stream); - this._TestLoadedTranslation(parser.Translations); + var parsedFile = parser.Parse(stream); + this._TestLoadedTranslation(parsedFile.Translations); } } @@ -56,13 +56,9 @@ public void TestManualEncoding() { using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test_KOI8-R.mo"))))) { - var parser = new MoFileParser() - { - Encoding = Encoding.GetEncoding("KOI8-R"), - DetectEncoding = false, - }; - parser.Parse(stream); - this._TestLoadedTranslation(parser.Translations); + var parser = new MoFileParser(Encoding.GetEncoding("KOI8-R"), false); + var parsedFile = parser.Parse(stream); + this._TestLoadedTranslation(parsedFile.Translations); } } @@ -71,8 +67,8 @@ private void _TestLoadedTranslation(IDictionary dict) Assert.Equal(new[] { "тест" }, dict["test"]); Assert.Equal(new[] { "тест2" }, dict["test2"]); Assert.Equal(new[] { "{0} минута", "{0} минуты", "{0} минут" }, dict["{0} minute"]); - Assert.Equal(new[] { "тест3контекст1" }, dict["context1" + BaseCatalog.CONTEXT_GLUE + "test3"]); - Assert.Equal(new[] { "тест3контекст2" }, dict["context2" + BaseCatalog.CONTEXT_GLUE + "test3"]); + Assert.Equal(new[] { "тест3контекст1" }, dict["context1" + Catalog.CONTEXT_GLUE + "test3"]); + Assert.Equal(new[] { "тест3контекст2" }, dict["context2" + Catalog.CONTEXT_GLUE + "test3"]); } } } \ No newline at end of file diff --git a/test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs b/test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs deleted file mode 100644 index e15ef1c..0000000 --- a/test/NGettext.Tests/Stabs/EmptyBaseCatalog.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; - -namespace NGettext.Tests.Stabs -{ - public class EmptyBaseCatalog : Catalog - { - public EmptyBaseCatalog() : base(CultureInfo.CurrentUICulture) { } - - public EmptyBaseCatalog(CultureInfo cultureInfo) : base(cultureInfo) { } - } -} \ No newline at end of file From a2e56cc3e15e06b751b747b2d2d265a1d12d1435 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 Jan 2016 18:45:40 +0300 Subject: [PATCH 50/55] README update. --- README.md | 20 ++++++++++++++++---- doc/examples/T.cs | 6 ++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f70d01d..9ba011d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,16 @@ It uses precompiled plural form rules and supports custom plural form rules pass +Build status +------------ + +|OS |Target frameworks (build)|Target frameworks (test)|Status| +|:--|:--|:--|:--| +|Windows|net20 net35 net40 net45 net46
    net35-client net40-client
    dnx451
    dnxcore50 uap10.0|dnx451|[![Build Status](https://ci.appveyor.com/api/projects/status/oc151pvllqqy0po9?svg=true)](https://ci.appveyor.com/project/neris/ngettext)| +|Linux|dnx451-mono|dnx451-mono|[![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext)| + + + Why not others? --------------- @@ -64,7 +74,7 @@ Now you can use NGettext in your code: // or // This will load translations from "./locale/ru_RU/LC_MESSAGES/Example.mo" - ICatalog catalog = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("ru-RU")); + ICatalog catalog = new Catalog("Example", "./locale", new CultureInfo("ru-RU")); ``` ```csharp Console.WriteLine(catalog.GetString("Hello, World!")); // will translate "Hello, World!" using loaded translations @@ -129,10 +139,10 @@ If you using this library under CoreCLR and you want to use encodings different ```csharp // "./locale/en_US/LC_MESSAGES/Example.mo" - ICatalog example_en = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("en-US")); + ICatalog example_en = new Catalog("Example", "./locale", new CultureInfo("en-US")); // "./locale/fr/LC_MESSAGES/Example.mo" - ICatalog example_fr = new Catalog("Example", "./locale", CultureInfo.CreateSpecificCulture("fr")); + ICatalog example_fr = new Catalog("Example", "./locale", new CultureInfo("fr")); // "./locale//LC_MESSAGES/AnotherDomainName.mo" ICatalog anotherDomain = new Catalog("AnotherDomainName", "./locale"); @@ -144,7 +154,7 @@ If you using this library under CoreCLR and you want to use encodings different ```csharp Stream moFileStream = File.OpenRead("path/to/domain.mo"); - ICatalog catalog = new Catalog(moFileStream, CultureInfo.CreateSpecificCulture("en-US")); + ICatalog catalog = new Catalog(moFileStream, new CultureInfo("en-US")); ``` @@ -154,6 +164,8 @@ If you using this library under CoreCLR and you want to use encodings different ```csharp catalog.PluralRule = new PluralRule(numPlurals, n => ( n == 1 ? 0 : 1 )); ``` +Also you can create custom plural rule generator by implementing IPluralRuleGenerator interface, which will create +a PluralRule for any culture. diff --git a/doc/examples/T.cs b/doc/examples/T.cs index c4bbb91..2294db1 100644 --- a/doc/examples/T.cs +++ b/doc/examples/T.cs @@ -3,8 +3,10 @@ // // Usage: -// T._("Hello, World!"); -// T._n("You have {0} apple.", "You have {0} apples.", count, count); +// T._("Hello, World!"); // GetString +// T._n("You have {0} apple.", "You have {0} apples.", count, count); // GetPluralString +// T._p("Context", "Hello, World!"); // GetParticularString +// T._pn("Context", "You have {0} apple.", "You have {0} apples.", count, count); // GetParticularPluralString // namespace Example { From bc5471647bf0dd3a40a1f28570c59c7e7101db84 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 Jan 2016 18:46:05 +0300 Subject: [PATCH 51/55] Quiet DNX restore for CI builds. --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 892bf4f..c247b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ solution: NGettext.sln script: - dnvm list - - dnu restore + - dnu restore --quiet - cd src/NGettext - dnu build --framework dnx451 - cd ../.. diff --git a/appveyor.yml b/appveyor.yml index 29203e0..b2ac08d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: install: - dnvm install latest - - dnu restore + - dnu restore --quiet - nuget install secure-file -ExcludeVersion - secure-file\tools\secure-file -decrypt NGettext.snk.enc -secret %snk_secret% From 8a9b60244400bb7e347fc585619cf9c79aa8192d Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 Jan 2016 19:00:03 +0300 Subject: [PATCH 52/55] README update. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 9ba011d..c90c16a 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,6 @@ or through DNX Utility: $ dnu install NGettext ``` -Alternatively you can download [compiled binaries](https://github.com/neris/NGettext/releases) or the [source code](https://github.com/neris/NGettext) and add a reference to `NGettext.dll` or `NGettext.csproj` to your project. - - Now you can use NGettext in your code: ```csharp using NGettext; From 9f1886c558bde64c45e4fc504c572933ba6501c7 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Fri, 15 Jan 2016 19:48:27 +0300 Subject: [PATCH 53/55] Project configuration updated. --- src/NGettext/NGettext.xproj | 5 ++--- src/NGettext/project.json | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/NGettext/NGettext.xproj b/src/NGettext/NGettext.xproj index 31c10eb..c5abc4e 100644 --- a/src/NGettext/NGettext.xproj +++ b/src/NGettext/NGettext.xproj @@ -4,7 +4,6 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - a6e2d0f9-52f7-421a-a8c2-e43b3394c0b7 @@ -12,9 +11,9 @@ ..\..\artifacts\obj\$(MSBuildProjectName) ..\..\artifacts\bin\$(MSBuildProjectName)\ - 2.0 + - + \ No newline at end of file diff --git a/src/NGettext/project.json b/src/NGettext/project.json index a0e05e4..bb15ac8 100644 --- a/src/NGettext/project.json +++ b/src/NGettext/project.json @@ -1,7 +1,7 @@ { - "version": "0.3.0.0", + "version": "0.3.0.1", "title": "NGettext", - "description": "A .NET implementation of the GNU/Gettext library.", + "description": "A cross-platform .NET implementation of the GNU/Gettext library.", "owners": [ "Neris Ereptoris" ], "authors": [ "Neris Ereptoris" ], "tags": [ "ngettext", "gettext", "internationalization", "localization", "i18n", "l10n", "translate" ], @@ -19,6 +19,20 @@ "keyFile": "../../NGettext.snk" }, + "configurations": { + "Debug": { + "compilationOptions": { + "define": [ "DEBUG", "TRACE" ] + } + }, + "Release": { + "compilationOptions": { + "define": [ "RELEASE" ], + "optimize": true + } + } + }, + "packInclude": { "LICENSE": "../../LICENSE" }, From 233f744b121fb30ff5b002db69ff9b9ec09605d3 Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Sat, 16 Jan 2016 03:37:33 +0300 Subject: [PATCH 54/55] Plural rule parsing from the *.mo file header. --- NGettext.sln | 5 + README.md | 37 ++- VERSION | 2 +- src/NGettext/Plural/Ast/AstTokenParser.cs | 298 ++++++++++++++++++ src/NGettext/Plural/Ast/ParserException.cs | 11 + src/NGettext/Plural/Ast/Token.cs | 38 +++ src/NGettext/Plural/Ast/TokenDefinition.cs | 90 ++++++ src/NGettext/Plural/Ast/TokenType.cs | 110 +++++++ src/NGettext/Plural/AstPluralRule.cs | 129 ++++++++ src/NGettext/Plural/AstPluralRuleGenerator.cs | 47 ++- src/NGettext/Plural/IPluralRule.cs | 4 +- src/NGettext/Properties/AssemblyInfo.cs | 4 +- .../Loaders/MoAstPluralLoaderTest.cs | 52 +++ .../Plural/Ast/AstTokenParserTest.cs | 119 +++++++ .../Plural/AstPluralRuleGeneratorTest.cs | 25 ++ 15 files changed, 951 insertions(+), 20 deletions(-) create mode 100644 src/NGettext/Plural/Ast/AstTokenParser.cs create mode 100644 src/NGettext/Plural/Ast/ParserException.cs create mode 100644 src/NGettext/Plural/Ast/Token.cs create mode 100644 src/NGettext/Plural/Ast/TokenDefinition.cs create mode 100644 src/NGettext/Plural/Ast/TokenType.cs create mode 100644 src/NGettext/Plural/AstPluralRule.cs create mode 100644 test/NGettext.Tests/Loaders/MoAstPluralLoaderTest.cs create mode 100644 test/NGettext.Tests/Plural/Ast/AstTokenParserTest.cs create mode 100644 test/NGettext.Tests/Plural/AstPluralRuleGeneratorTest.cs diff --git a/NGettext.sln b/NGettext.sln index 1cbd48b..02298be 100644 --- a/NGettext.sln +++ b/NGettext.sln @@ -7,7 +7,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{11866FB2-5A5 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B2C3CAAC-6C5B-48C2-9895-964882670F4D}" ProjectSection(SolutionItems) = preProject + .travis.yml = .travis.yml + appveyor.yml = appveyor.yml global.json = global.json + LICENSE = LICENSE + README.md = README.md + VERSION = VERSION EndProjectSection EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NGettext", "src\NGettext\NGettext.xproj", "{A6E2D0F9-52F7-421A-A8C2-E43B3394C0B7}" diff --git a/README.md b/README.md index c90c16a..9fbd9bf 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,8 @@ Works fine on Microsoft .NET Framework version 2.0 or higher, Mono and even on . This implementation loads translations directly from gettext *.mo files (no need to compile a satellite assembly) and can handle multiple translation domains and multiple locales in one application instance. It supports both little-endian and big-endian MO files, automatic (header-based) encoding detection. -NGettext currently not supports loading plural form rules from *.mo file headers. -It uses precompiled plural form rules and supports custom plural form rules passed through API. - - - -Build status ------------- - -|OS |Target frameworks (build)|Target frameworks (test)|Status| -|:--|:--|:--|:--| -|Windows|net20 net35 net40 net45 net46
    net35-client net40-client
    dnx451
    dnxcore50 uap10.0|dnx451|[![Build Status](https://ci.appveyor.com/api/projects/status/oc151pvllqqy0po9?svg=true)](https://ci.appveyor.com/project/neris/ngettext)| -|Linux|dnx451-mono|dnx451-mono|[![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext)| +By default, NGettext uses pre-compiled plural form rules for most known locales. +You can enable plural form rule parsing from *.mo file headers or use a custom plural rules (see description below). @@ -37,7 +27,7 @@ It uses satellite assemblies as a translation files and does not support multipl It's hard to build and maintain translation files and change locale inside your application. **So why NGettext?** -* NGettext is fully cross-platform as it don't uses any native or managed 3rd-party libraries. +* NGettext is fully cross-platform as it doesn't use any native or managed 3rd-party libraries. * NGettext supports multiple domains. You can separate translation files for each of your application's module or plugin. * NGettext supports multiple locales in one application instance and gives really simple API to choose locale of your application. You don't even need to care about locales of your application's threads. @@ -47,6 +37,16 @@ It's hard to build and maintain translation files and change locale inside your +Build status +------------ + +|OS |Target frameworks (build)|Target frameworks (test)|Status| +|:--|:--|:--|:--| +|Windows|net20 net35 net40 net45 net46
    net35-client net40-client
    dnx451
    dnxcore50 uap10.0|dnx451|[![Build Status](https://ci.appveyor.com/api/projects/status/oc151pvllqqy0po9?svg=true)](https://ci.appveyor.com/project/neris/ngettext)| +|Linux|dnx451-mono|dnx451-mono|[![Build Status](https://travis-ci.org/neris/NGettext.svg?branch=master)](https://travis-ci.org/neris/NGettext)| + + + Installation and usage ---------------------- @@ -156,6 +156,17 @@ If you using this library under CoreCLR and you want to use encodings different +### Parsing plural rules from the *.mo file header + +To support this you can just create catalog using `MoAstPluralLoader`. +```csharp + ICatalog catalog = new Catalog(new MoAstPluralLoader("Example", "./locale")); +``` +Please note that this solution is slightly slower than NGettext default behavior even it's pretty well optimized. +However, in most cases, performance degradation will not be noticeable. + + + ### Custom plural formulas ```csharp diff --git a/VERSION b/VERSION index 73082a8..3d2da89 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.0.0 \ No newline at end of file +0.4.0.0 \ No newline at end of file diff --git a/src/NGettext/Plural/Ast/AstTokenParser.cs b/src/NGettext/Plural/Ast/AstTokenParser.cs new file mode 100644 index 0000000..8a52520 --- /dev/null +++ b/src/NGettext/Plural/Ast/AstTokenParser.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NGettext.Plural.Ast +{ + /// + /// Plural rule formula parser. + /// Ported from the I18n component from Zend Framework (https://github.com/zendframework/zf2). + /// + public class AstTokenParser + { + protected readonly Dictionary TokenDefinitions = new Dictionary(); + + protected string Input; + + protected int Position; + + protected Token CurrentToken; + + /// + /// Initializes a new instance of the class with default token definitions. + /// + public AstTokenParser() + { + // Ternary operators + this.RegisterTokenDefinition(TokenType.TernaryIf, 20) + .SetLeftDenotationGetter((self, left) => { + self.Children[0] = left; + self.Children[1] = this.ParseNextExpression(); + this.AdvancePosition(TokenType.TernaryElse); + self.Children[2] = this.ParseNextExpression(); + return self; + }); + this.RegisterTokenDefinition(TokenType.TernaryElse); + + // Boolean operators + this.RegisterLeftInfixTokenDefinition(TokenType.Or, 30); + this.RegisterLeftInfixTokenDefinition(TokenType.And, 40); + + // Equal operators + this.RegisterLeftInfixTokenDefinition(TokenType.Equals, 50); + this.RegisterLeftInfixTokenDefinition(TokenType.NotEquals, 50); + + // Compare operators + this.RegisterLeftInfixTokenDefinition(TokenType.GreaterThan, 50); + this.RegisterLeftInfixTokenDefinition(TokenType.LessThan, 50); + this.RegisterLeftInfixTokenDefinition(TokenType.GreaterOrEquals, 50); + this.RegisterLeftInfixTokenDefinition(TokenType.LessOrEquals, 50); + + // Add operators + this.RegisterLeftInfixTokenDefinition(TokenType.Minus, 60); + this.RegisterLeftInfixTokenDefinition(TokenType.Plus, 60); + + // Multiply operators + this.RegisterLeftInfixTokenDefinition(TokenType.Multiply, 70); + this.RegisterLeftInfixTokenDefinition(TokenType.Divide, 70); + this.RegisterLeftInfixTokenDefinition(TokenType.Modulo, 70); + + // Not operator + this.RegisterPrefixTokenDefinition(TokenType.Not, 80); + + // Literals + this.RegisterTokenDefinition(TokenType.N) + .SetNullDenotationGetter((self) => { + return self; + }); + this.RegisterTokenDefinition(TokenType.Number) + .SetNullDenotationGetter((self) => { + return self; + }); + + // Parentheses + this.RegisterTokenDefinition(TokenType.LeftParenthesis) + .SetNullDenotationGetter((self) => { + var expression = this.ParseNextExpression(); + this.AdvancePosition(TokenType.RightParenthesis); + return expression; + }); + this.RegisterTokenDefinition(TokenType.RightParenthesis); + + // EOF + this.RegisterTokenDefinition(TokenType.EOF); + } + + protected TokenDefinition RegisterTokenDefinition(TokenType tokenType, int leftBindingPower = 0) + { + TokenDefinition definition; + if (this.TokenDefinitions.TryGetValue(tokenType, out definition)) + { + definition.LeftBindingPower = Math.Max(definition.LeftBindingPower, leftBindingPower); + } + else + { + definition = new TokenDefinition(tokenType, leftBindingPower); + this.TokenDefinitions[tokenType] = definition; + } + + return definition; + } + + protected TokenDefinition RegisterLeftInfixTokenDefinition(TokenType tokenType, int leftBindingPower) + { + return this.RegisterTokenDefinition(tokenType, leftBindingPower) + .SetLeftDenotationGetter((self, left) => { + self.Children[0] = left; + self.Children[1] = this.ParseNextExpression(leftBindingPower); + return self; + }); + } + + protected TokenDefinition RegisterRightInfixTokenDefinition(TokenType tokenType, int leftBindingPower) + { + return this.RegisterTokenDefinition(tokenType, leftBindingPower) + .SetLeftDenotationGetter((self, left) => { + self.Children[0] = left; + self.Children[1] = this.ParseNextExpression(leftBindingPower - 1); + return self; + }); + } + + protected TokenDefinition RegisterPrefixTokenDefinition(TokenType tokenType, int leftBindingPower) + { + return this.RegisterTokenDefinition(tokenType, leftBindingPower) + .SetNullDenotationGetter((self) => { + self.Children[0] = this.ParseNextExpression(leftBindingPower); + self.Children[1] = null; + return self; + }); + } + + protected TokenDefinition GetDefinition(TokenType tokenType) + { + TokenDefinition tokenDefinition; + if (!this.TokenDefinitions.TryGetValue(tokenType, out tokenDefinition)) + { + throw new ParserException(String.Format("Can not find token definition for \"\" token type.", tokenType)); + } + return tokenDefinition; + } + + /// + /// Parses the input string that contains a plural rule formula and generates an abstract syntax tree. + /// + /// Input string. + /// Root node of the abstract syntax tree. + public Token Parse(string input) + { + this.Input = input + "\0"; + this.Position = 0; + this.CurrentToken = this.GetNextToken(); + + return this.ParseNextExpression(); + } + + protected Token ParseNextExpression(int rightBindingPower = 0) + { + var token = this.CurrentToken; + this.CurrentToken = this.GetNextToken(); + var left = this.GetDefinition(token.Type).GetNullDenotation(token); + + while (rightBindingPower < this.GetDefinition(this.CurrentToken.Type).LeftBindingPower) + { + token = this.CurrentToken; + this.CurrentToken = this.GetNextToken(); + left = this.GetDefinition(token.Type).GetLeftDenotation(token, left); + } + + return left; + } + + protected void AdvancePosition() + { + this.CurrentToken = this.GetNextToken(); + } + + protected void AdvancePosition(TokenType expectedTokenType) + { + if (this.CurrentToken.Type != expectedTokenType) + { + throw new ParserException(String.Format("Expected token \"{0}\" but received \"{1}\"", expectedTokenType, this.CurrentToken.Type)); + } + this.AdvancePosition(); + } + + protected Token GetNextToken() + { + while (this.Input[this.Position] == ' ' || this.Input[this.Position] == '\t') { + this.Position++; + } + + var character = this.Input[this.Position++]; + var tokenType = TokenType.None; + var value = 0L; + + switch (character) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + var sb = new StringBuilder(); + sb.Append(character); + while (Char.IsNumber(this.Input[this.Position])) + { + sb.Append(this.Input[this.Position++]); + } + tokenType = TokenType.Number; + value = long.Parse(sb.ToString()); + break; + + case '=': + case '&': + case '|': + if (this.Input[this.Position] == character) + { + this.Position++; + switch (character) + { + case '=': tokenType = TokenType.Equals; break; + case '&': tokenType = TokenType.And; break; + case '|': tokenType = TokenType.Or; break; + } + } + else + { + throw new ParserException(String.Format("Found invalid character \"{0}\" after character \"{1}\" in input stream.", this.Input[this.Position], character)); + } + break; + + case '!': + if (this.Input[this.Position] == '=') + { + this.Position++; + tokenType = TokenType.NotEquals; + } + else + { + tokenType = TokenType.Not; + } + break; + + case '<': + if (this.Input[this.Position] == '=') + { + this.Position++; + tokenType = TokenType.LessOrEquals; + } + else + { + tokenType = TokenType.LessThan; + } + break; + + case '>': + if (this.Input[this.Position] == '=') + { + this.Position++; + tokenType = TokenType.GreaterOrEquals; + } + else + { + tokenType = TokenType.GreaterThan; + } + break; + + case '*': tokenType = TokenType.Multiply; break; + case '/': tokenType = TokenType.Divide; break; + case '%': tokenType = TokenType.Modulo; break; + case '+': tokenType = TokenType.Plus; break; + case '-': tokenType = TokenType.Minus; break; + case 'n': tokenType = TokenType.N; break; + case '?': tokenType = TokenType.TernaryIf; break; + case ':': tokenType = TokenType.TernaryElse; break; + case '(': tokenType = TokenType.LeftParenthesis; break; + case ')': tokenType = TokenType.RightParenthesis; break; + + case ';': + case '\n': + case '\0': + tokenType = TokenType.EOF; + this.Position--; + break; + + default: + throw new ParserException(String.Format("Found invalid character \"{0}\" in input stream at position {1}.", character, this.Position)); + } + + return new Token(tokenType, value); + } + } +} diff --git a/src/NGettext/Plural/Ast/ParserException.cs b/src/NGettext/Plural/Ast/ParserException.cs new file mode 100644 index 0000000..b08af01 --- /dev/null +++ b/src/NGettext/Plural/Ast/ParserException.cs @@ -0,0 +1,11 @@ +using System; + +namespace NGettext.Plural.Ast +{ + public class ParserException : Exception + { + public ParserException() : base() { } + public ParserException(string message) : base(message) { } + public ParserException(string message, Exception innerException) : base(message, innerException) { } + } +} diff --git a/src/NGettext/Plural/Ast/Token.cs b/src/NGettext/Plural/Ast/Token.cs new file mode 100644 index 0000000..1c746d7 --- /dev/null +++ b/src/NGettext/Plural/Ast/Token.cs @@ -0,0 +1,38 @@ +using System; + +namespace NGettext.Plural.Ast +{ + /// + /// Represents a node in the abstract syntax tree. + /// + public class Token + { + public const int MAX_CHILDREN_COUNT = 3; + + /// + /// Gets the type of the current token. + /// + public TokenType Type { get; protected set; } + + /// + /// Gets or sets an optional value associated with this token. + /// + public long Value { get; set; } + + /// + /// Gets token children. + /// + public readonly Token[] Children = new Token[MAX_CHILDREN_COUNT]; + + /// + /// Initializes a new instance of the class with given type and (optional) value. + /// + /// + /// + public Token(TokenType type, long value = 0) + { + this.Type = type; + this.Value = value; + } + } +} diff --git a/src/NGettext/Plural/Ast/TokenDefinition.cs b/src/NGettext/Plural/Ast/TokenDefinition.cs new file mode 100644 index 0000000..02a86b8 --- /dev/null +++ b/src/NGettext/Plural/Ast/TokenDefinition.cs @@ -0,0 +1,90 @@ +using System; + +namespace NGettext.Plural.Ast +{ + /// + /// A token definition that describes behavior of token with specified type. + /// + public class TokenDefinition + { + public delegate Token NullDenotationGetterDelegate(Token self); + public delegate Token LeftDenotationGetterDelegate(Token self, Token left); + + /// + /// Gets type of the token this definition associated with. + /// + public TokenType TokenType { get; protected set; } + + /// + /// Gets or sets a left binding power. + /// + public int LeftBindingPower { get; set; } + + protected NullDenotationGetterDelegate NullDenotationGetter; + protected LeftDenotationGetterDelegate LeftDenotationGetter; + + /// + /// Initializes a new instance of the class for given token type with given left binding power. + /// + /// + /// + public TokenDefinition(TokenType tokenType, int leftBindingPower) + { + this.TokenType = tokenType; + this.LeftBindingPower = leftBindingPower; + } + + /// + /// Sets a null denotation getter. + /// + /// + /// + public TokenDefinition SetNullDenotationGetter(NullDenotationGetterDelegate nullDenotationGetter) + { + this.NullDenotationGetter = nullDenotationGetter; + return this; + } + + /// + /// Sets a left denotation getter. + /// + /// + /// + public TokenDefinition SetLeftDenotationGetter(LeftDenotationGetterDelegate leftDenotationGetter) + { + this.LeftDenotationGetter = leftDenotationGetter; + return this; + } + + /// + /// Gets a null denotation token for given token using the null denotation getter. + /// + /// + /// + public Token GetNullDenotation(Token self) + { + if (this.NullDenotationGetter == null) + throw new InvalidOperationException("Unable to invoke null denotation getter: getter is not set."); + if (self.Type != this.TokenType) + throw new ArgumentException("Unable to invoke null denotation getter: invalid self type.", "self"); + + return this.NullDenotationGetter(self); + } + + /// + /// Gets a left denotation token for given token using the left denotation getter. + /// + /// + /// + /// + public Token GetLeftDenotation(Token self, Token left) + { + if (this.LeftDenotationGetter == null) + throw new InvalidOperationException("Unable to invoke left denotation getter: getter is not set."); + if (self.Type != this.TokenType) + throw new ArgumentException("Unable to invoke null denotation getter: invalid self type.", "self"); + + return this.LeftDenotationGetter(self, left); + } + } +} diff --git a/src/NGettext/Plural/Ast/TokenType.cs b/src/NGettext/Plural/Ast/TokenType.cs new file mode 100644 index 0000000..1f32fdc --- /dev/null +++ b/src/NGettext/Plural/Ast/TokenType.cs @@ -0,0 +1,110 @@ +using System; + +namespace NGettext.Plural.Ast +{ + public enum TokenType : int + { + None, + + /// + /// ? + /// + TernaryIf, + + /// + /// : + /// + TernaryElse, + + /// + /// || + /// + Or, + + /// + /// && + /// + And, + + /// + /// == + /// + Equals, + + /// + /// != + /// + NotEquals, + + /// + /// > + /// + GreaterThan, + + /// + /// < + /// + LessThan, + + /// + /// >= + /// + GreaterOrEquals, + + /// + /// <= + /// + LessOrEquals, + + /// + /// - + /// + Minus, + + /// + /// + + /// + Plus, + + /// + /// * + /// + Multiply, + + /// + /// / + /// + Divide, + + /// + /// % + /// + Modulo, + + /// + /// ! + /// + Not, + + /// + /// n + /// + N, + + + Number, + + /// + /// ( + /// + LeftParenthesis, + + /// + /// ) + /// + RightParenthesis, + + + EOF, + } +} diff --git a/src/NGettext/Plural/AstPluralRule.cs b/src/NGettext/Plural/AstPluralRule.cs new file mode 100644 index 0000000..b2e3e61 --- /dev/null +++ b/src/NGettext/Plural/AstPluralRule.cs @@ -0,0 +1,129 @@ +using System; +using NGettext.Plural.Ast; + +namespace NGettext.Plural +{ + /// + /// Represents a plural rule that will evaluate a given number + /// using an abstract syntax tree generated by a plural rule formula parser. + /// + public class AstPluralRule : IPluralRule + { + /// + /// Maximum number of plural forms supported. + /// + public int NumPlurals { get; protected set; } + + protected Token AstRoot { get; set; } + + /// + /// Initializes a new instance of the class with given NumPlurals and abstract syntax tree. + /// + /// + /// Abstract syntax tree root. + public AstPluralRule(int numPlurals, Token astRoot) + { + if (numPlurals <= 0) + throw new ArgumentOutOfRangeException("numPlurals"); + if (astRoot == null) + throw new ArgumentNullException("astRoot"); + + this.NumPlurals = numPlurals; + this.AstRoot = astRoot; + } + + /// + /// Evaluates a number and returns a plural form index. + /// + /// Number which needs to be evaluated. + /// Plural form index. + public int Evaluate(long number) + { + return (int)this.Evaluate(this.AstRoot, number); + } + + protected long Evaluate(Token node, long number) + { + switch (node.Type) + { + case TokenType.Number: + return node.Value; + + case TokenType.N: + return number; + + case TokenType.Plus: + return this.Evaluate(node.Children[0], number) + + this.Evaluate(node.Children[1], number); + + case TokenType.Minus: + return this.Evaluate(node.Children[0], number) + - this.Evaluate(node.Children[1], number); + + case TokenType.Divide: + return this.Evaluate(node.Children[0], number) + / this.Evaluate(node.Children[1], number); + + case TokenType.Multiply: + return this.Evaluate(node.Children[0], number) + * this.Evaluate(node.Children[1], number); + + case TokenType.Modulo: + return this.Evaluate(node.Children[0], number) + % this.Evaluate(node.Children[1], number); + + case TokenType.GreaterThan: + return this.Evaluate(node.Children[0], number) + > this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.GreaterOrEquals: + return this.Evaluate(node.Children[0], number) + >= this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.LessThan: + return this.Evaluate(node.Children[0], number) + < this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.LessOrEquals: + return this.Evaluate(node.Children[0], number) + <= this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.Equals: + return this.Evaluate(node.Children[0], number) + == this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.NotEquals: + return this.Evaluate(node.Children[0], number) + != this.Evaluate(node.Children[1], number) + ? 1 : 0; + + case TokenType.And: + return this.Evaluate(node.Children[0], number) != 0 + && this.Evaluate(node.Children[1], number) != 0 + ? 1 : 0; + + case TokenType.Or: + return this.Evaluate(node.Children[0], number) != 0 + || this.Evaluate(node.Children[1], number) != 0 + ? 1 : 0; + + case TokenType.Not: + return this.Evaluate(node.Children[0], number) == 0 + ? 1 : 0; + + case TokenType.TernaryIf: + return this.Evaluate(node.Children[0], number) != 0 + ? this.Evaluate(node.Children[1], number) + : this.Evaluate(node.Children[2], number); + + default: + throw new InvalidOperationException(String.Format("Can not evaluate token: {0}.", node.Type)); + } + } + } +} diff --git a/src/NGettext/Plural/AstPluralRuleGenerator.cs b/src/NGettext/Plural/AstPluralRuleGenerator.cs index 03d1bb6..74e309d 100644 --- a/src/NGettext/Plural/AstPluralRuleGenerator.cs +++ b/src/NGettext/Plural/AstPluralRuleGenerator.cs @@ -1,5 +1,7 @@ using System; using System.Globalization; +using System.Text.RegularExpressions; +using NGettext.Plural.Ast; namespace NGettext.Plural { @@ -8,16 +10,36 @@ namespace NGettext.Plural ///
    public class AstPluralRuleGenerator : DefaultPluralRuleGenerator, IPluralRuleTextParser { + private static readonly Regex NPluralsRegex = new Regex(@"(nplurals=(?\d+))", +#if DNXCORE50 + RegexOptions.IgnoreCase +#else + RegexOptions.IgnoreCase | RegexOptions.Compiled +#endif + ); + + private static readonly Regex PluralRegex = new Regex(@"(plural=(?[^;\n]+))", +#if DNXCORE50 + RegexOptions.IgnoreCase +#else + RegexOptions.IgnoreCase | RegexOptions.Compiled +#endif + ); + + /// /// Gets a plural rule text. /// protected string PluralRuleText { get; private set; } + public AstTokenParser Parser { get; set; } + /// /// Initializes a new instance of the class with no plural rule text. /// public AstPluralRuleGenerator() { + this.Parser = new AstTokenParser(); } /// @@ -48,11 +70,32 @@ public override IPluralRule CreateRule(CultureInfo cultureInfo) { if (this.PluralRuleText != null) { - //TODO: Try to parse pluralRuleText - + var numPlurals = this.ParseNumPlurals(this.PluralRuleText); + var plural = this.ParsePluralFormulaText(this.PluralRuleText); + var astTree = this.Parser.Parse(plural); + + return new AstPluralRule(numPlurals, astTree); } return base.CreateRule(cultureInfo); } + + public int ParseNumPlurals(string input) + { + var match = NPluralsRegex.Match(input); + if (!match.Success) + throw new FormatException("Failed to parse 'nplurals' parameter from the plural rule text: invalid format"); + + return int.Parse(match.Groups["nplurals"].Value); + } + + public string ParsePluralFormulaText(string input) + { + var match = PluralRegex.Match(input); + if (!match.Success) + throw new FormatException("Failed to parse 'plural' parameter from the plural rule text: invalid format"); + + return match.Groups["plural"].Value; + } } } \ No newline at end of file diff --git a/src/NGettext/Plural/IPluralRule.cs b/src/NGettext/Plural/IPluralRule.cs index 0b89f08..e013e0b 100644 --- a/src/NGettext/Plural/IPluralRule.cs +++ b/src/NGettext/Plural/IPluralRule.cs @@ -3,7 +3,7 @@ namespace NGettext.Plural { /// - /// Represents a plural form rule whitch can generate a plural form index by given number. + /// Represents a plural form rule which can generate a plural form index by given number. /// public interface IPluralRule { @@ -15,7 +15,7 @@ public interface IPluralRule /// /// Evaluates a number and returns a plural form index. /// - /// Number whitch needs to be evaluated. + /// Number which needs to be evaluated. /// Plural form index. int Evaluate(long number); } diff --git a/src/NGettext/Properties/AssemblyInfo.cs b/src/NGettext/Properties/AssemblyInfo.cs index b16c022..7a4d6bf 100644 --- a/src/NGettext/Properties/AssemblyInfo.cs +++ b/src/NGettext/Properties/AssemblyInfo.cs @@ -13,8 +13,8 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("0.3.0.0")] -[assembly: AssemblyFileVersion("0.3.0.0")] +[assembly: AssemblyVersion("0.4.0.0")] +[assembly: AssemblyFileVersion("0.4.0.0")] [assembly: Guid("9ef9b9d7-7df8-4c3a-ac8c-58bea65f0526")] diff --git a/test/NGettext.Tests/Loaders/MoAstPluralLoaderTest.cs b/test/NGettext.Tests/Loaders/MoAstPluralLoaderTest.cs new file mode 100644 index 0000000..9b1ebca --- /dev/null +++ b/test/NGettext.Tests/Loaders/MoAstPluralLoaderTest.cs @@ -0,0 +1,52 @@ +using System.Globalization; +using System.IO; +using Xunit; +using NGettext.Loaders; +using System.Collections.Generic; + +namespace NGettext.Tests.Loaders +{ + public class MoAstPluralLoaderTest + { + public string LocalesDir; + + public MoAstPluralLoaderTest() + { + this.LocalesDir = Path.Combine(Directory.GetCurrentDirectory(), Path.Combine("TestResources", "locales")); + } + + public static IEnumerable GetTestAstPluralRuleGeneratorData() + { + yield return new object[] { 1, "1 минута" }; + yield return new object[] { 2, "2 минуты" }; + yield return new object[] { 3, "3 минуты" }; + yield return new object[] { 4, "4 минуты" }; + yield return new object[] { 5, "5 минут" }; + yield return new object[] { 6, "6 минут" }; + yield return new object[] { 7, "7 минут" }; + yield return new object[] { 8, "8 минут" }; + yield return new object[] { 9, "9 минут" }; + yield return new object[] { 10, "10 минут" }; + yield return new object[] { 11, "11 минут" }; + yield return new object[] { 21, "21 минута" }; + yield return new object[] { 22, "22 минуты" }; + yield return new object[] { 25, "25 минут" }; + yield return new object[] { 101, "101 минута" }; + } + + [Fact] + public void TestAstPluralRuleGenerator() + { + using (var stream = File.OpenRead(Path.Combine(LocalesDir, Path.Combine("ru_RU", Path.Combine("LC_MESSAGES", "Test.mo"))))) + { + var ignoredConflictingCulture = new CultureInfo("en-US"); + var t = new Catalog(new MoAstPluralLoader(stream), ignoredConflictingCulture); + + foreach (object[] mapping in GetTestAstPluralRuleGeneratorData()) + { + Assert.Equal((string)mapping[1], t.GetPluralString("{0} minute", "{0} minutes", (int)mapping[0], (int)mapping[0])); + } + } + } + } +} diff --git a/test/NGettext.Tests/Plural/Ast/AstTokenParserTest.cs b/test/NGettext.Tests/Plural/Ast/AstTokenParserTest.cs new file mode 100644 index 0000000..e796fff --- /dev/null +++ b/test/NGettext.Tests/Plural/Ast/AstTokenParserTest.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using NGettext.Plural; +using NGettext.Plural.Ast; +using Xunit; + +namespace NGettext.Tests.Plural.Ast +{ + public class AstTokenParserTest + { + public static IEnumerable GetParseRulesTestData() + { + // Basic calculations + yield return new object[] { "addition" , "2 + 3", 5 }; + yield return new object[] { "substraction" , "3 - 2", 1 }; + yield return new object[] { "multiplication" , "2 * 3", 6 }; + yield return new object[] { "division" , "6 / 3", 2 }; + yield return new object[] { "integer-division" , "7 / 4", 1 }; + yield return new object[] { "modulo" , "7 % 4", 3 }; + // Boolean NOT + yield return new object[] { "boolean-not-0" , "!0", 1 }; + yield return new object[] { "boolean-not-1" , "!1", 0 }; + yield return new object[] { "boolean-not-15" , "!1", 0 }; + // Equal operators + yield return new object[] { "equal-true" , "5 == 5", 1 }; + yield return new object[] { "equal-false" , "5 == 4", 0 }; + yield return new object[] { "not-equal-true" , "5 != 5", 0 }; + yield return new object[] { "not-equal-false" , "5 != 4", 1 }; + // Compare operators + yield return new object[] { "less-than-true" , "5 > 4", 1 }; + yield return new object[] { "less-than-false" , "5 > 5", 0 }; + yield return new object[] { "less-or-equal-true" , "5 >= 5", 1 }; + yield return new object[] { "less-or-equal-false" , "5 >= 6", 0 }; + yield return new object[] { "greater-than-true" , "5 < 6", 1 }; + yield return new object[] { "greater-than-false" , "5 < 5", 0 }; + yield return new object[] { "greater-or-equal-true" , "5 <= 5", 1 }; + yield return new object[] { "greater-or-equal-false" , "5 <= 4", 0 }; + // Boolean operators + yield return new object[] { "boolean-and-true" , "1 && 1", 1 }; + yield return new object[] { "boolean-and-false" , "1 && 0", 0 }; + yield return new object[] { "boolean-or-true" , "1 || 0", 1 }; + yield return new object[] { "boolean-or-false" , "0 || 0", 0 }; + // Variable injection + yield return new object[] { "variable-injection" , "n", 0 }; + } + + [Fact] + public void ParseRulesTest() + { + var parser = new AstTokenParser(); + foreach (object[] mapping in GetParseRulesTestData()) + { + var astTree = parser.Parse((string)mapping[1]); + var rule = new AstPluralRule(100, astTree); + Assert.Equal((int)mapping[2], rule.Evaluate(0)); + } + } + + public static IEnumerable GetParseCompleteRulesTestData() + { + // Taken from original gettext tests + yield return new object[] { + "n != 1", + "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }; + yield return new object[] { + "n>1", + "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }; + yield return new object[] { + "n==1 ? 0 : n==2 ? 1 : 2", + "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" + }; + yield return new object[] { + "n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2", + "10111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222" + }; + yield return new object[] { + "n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2", + "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111" + }; + yield return new object[] { + "n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2", + "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222" + }; + yield return new object[] { + "n%100/10==1 ? 2 : n%10==1 ? 0 : (n+9)%10>3 ? 2 : 1", + "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222" + }; + yield return new object[] { + "n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2", + "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222" + }; + yield return new object[] { + "n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3", + "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333" + }; + } + + [Fact] + public void ParseCompleteRulesTest() + { + var parser = new AstTokenParser(); + var t = 0; + foreach (object[] mapping in GetParseCompleteRulesTestData()) + { + var astTree = parser.Parse((string)mapping[0]); + var rule = new AstPluralRule(100, astTree); + var expectedSeq = (string)mapping[1]; + + for (int i = 0; i < 200; i++) + { + var expected = int.Parse(expectedSeq[i].ToString()); + Assert.Equal(expected, rule.Evaluate(i)); + } + } + } + } +} diff --git a/test/NGettext.Tests/Plural/AstPluralRuleGeneratorTest.cs b/test/NGettext.Tests/Plural/AstPluralRuleGeneratorTest.cs new file mode 100644 index 0000000..41dc4f8 --- /dev/null +++ b/test/NGettext.Tests/Plural/AstPluralRuleGeneratorTest.cs @@ -0,0 +1,25 @@ +using System; +using Xunit; +using NGettext.Plural; + +namespace NGettext.Tests.Plural +{ + public class AstPluralRuleGeneratorTest + { + + [Fact] + public void ParseNumPluralsTest() + { + var generator = new AstPluralRuleGenerator(); + Assert.Equal(9, generator.ParseNumPlurals("nplurals=9; plural=n")); + } + + [Fact] + public void ParsePluralFormulaTextTest() + { + var generator = new AstPluralRuleGenerator(); + var formulaString = "n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2"; + Assert.Equal(formulaString, generator.ParsePluralFormulaText("nplurals=9; plural=" + formulaString)); + } + } +} From 07e36df51291f083ca44b133eb9921ac1fc1e65e Mon Sep 17 00:00:00 2001 From: Neris Ereptoris Date: Sat, 16 Jan 2016 03:38:51 +0300 Subject: [PATCH 55/55] Project version bump. --- src/NGettext/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NGettext/project.json b/src/NGettext/project.json index bb15ac8..622b65c 100644 --- a/src/NGettext/project.json +++ b/src/NGettext/project.json @@ -1,5 +1,5 @@ { - "version": "0.3.0.1", + "version": "0.4.0.0", "title": "NGettext", "description": "A cross-platform .NET implementation of the GNU/Gettext library.", "owners": [ "Neris Ereptoris" ],