ASP.NET Localization with singular and plural
Asked Answered
D

7

20

Can I with ASP.NET Resources/Localization translate strings to depend on one or other (the English grammar) in a easy way, like I pass number 1 in my translate, it return "You have one car" or with 0, 2 and higher, "You have %n cars"?

Or I'm forced to have logic in my view to see if it's singular or plural?

Dolly answered 17/12, 2008 at 22:57 Comment(0)
C
39

JasonTrue wrote:

To the best of my knowledge, there isn't a language that requires something more complicated than singular/plural

Such languages do exist. In my native Polish, for example, there are three forms: for 1, for 2-4 and for zero and numbers greater than 4. Then after you reach 20, the forms for 21, 22-24 and 25+ are again different (same grammatical forms as for numerals 0-9). And yes, "you have 0 things" sounds awkward, because you're not likely to see that used in real life.

As a localization specialist, here's what I would recommend:

If possible, use forms which put the numeral at the end:

a: Number of cars: %d

This means the form of the noun "car" does not depend on the numeral, and 0 is as natural as any other number.

If the above is not acceptable, at least always make a complete sentence a translatable resource. That is, do use

b: You have 1 car.    
c: You have %d cars.

But never split such units into smaller fragments such as

d: You have
e: car(s)

(Then somewhere else you have a non-localizable resource such as %s %d %s)

The difference is that while I cannot translate (c) directly, since the form of the noun will change, I can see the problem and I can change the sentence to form (a) in translation.

On the other hand, when I am faced with (d) and (e) fragments, there is no way to make sure the resulting sentence will be grammatical. Again: using fragments guarantees that in some languages the translation will be anything from grammatically awkward to completely broken.

This applies across the board, not just to numerals. For example, a fragment such as %s was deleted is also untranslatable, since the form of the verb will depend on the gender of the noun, which is unavailable here. The best I can do for Polish is the equivalent of Deleted: %s, but I can only do it as long as the %s placeholder is included in the translatable resource. If all I have is "was deleted" with no clue to the referent noun, I can only startle my dog by cursing aloud and in the end I still have to produce garbage grammar.

Chapfallen answered 23/12, 2008 at 22:29 Comment(3)
Great suggestions and +1 for educating me on multiple plural forms.Misty
in Arabic, there are 3 forms: singular, dual and pluralArequipa
Amazing response, but what is your suggestion for handling it "correctly" then? I see you mentioned the form a that would work for everything, but it is a workaround solution.Amass
R
8

I've been working on a library to assist with internationalization of an application. It's called SmartFormat and is open-source on GitHub.

It contains "grammatical number" rules for many languages that determine the correct singular/plural form based on the locale. When translating a phrase that has words that depend on a quantity, you specify the multiple forms and the formatter chooses the correct form based on these rules.

For example:

var message = "There {0:is:are} {0} {0:item:items} remaining.";
var output = Smart.Format(culture, message, items.Count);

It has a very similar syntax to String.Format(...), but has tons of great features that make it easy to create natural and grammatically-correct messages.

It also deals with possible gender-specific formatting, lists, and much more.

Rail answered 25/8, 2011 at 1:36 Comment(0)
S
3

moodforaday wrote:

This applies across the board, not just to numerals. For example, a fragment such as "%s was deleted" is also untranslatable, since the form of the verb will depend on the gender of the noun, which is unavailable here. The best I can do for Polish is the equivalent of "Deleted: %s", but I can only do it as long as the %s placeholder is included in the translatable resource. If all I have is "was deleted" with no clue to the referent noun, I can only startle my dog by cursing aloud and in the end I still have to produce garbage grammar.

The point I would like to make here, is never include a noun as a parameter. Many European languages modify the noun based on its gender, and in the case of German, whether it is the subject, object, or indirect object. Just use separate messages. Instead of, "%s was deleted.", use a separate translation string for each type: "The transaction was deleted." "The user was deleted." etc.

This way, each string can be translated properly.

The solution to handle plural forms in different languages can be found here: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html

While you can't use the above software in a commercial application (it's covered under GPL), you can use the same concepts. Their plural form expressions fit perfectly with lambda expressions in .NET. There are a limited number of plural form expressions that cover a large number of languages. You can map a particular language to a lambda expression that calculates which plural form to use based on the language. Then, look up the appropriate plural form in a .NET resx file.

Sian answered 23/8, 2009 at 19:30 Comment(1)
You can use gettext in commercial applications. Getttext tools are under GPL, but the gettext library is under LGPL. In some past project I was using it (via .NET implementation of gettext, available in gettext itself) and we get a confirmation from my company very competent legal department that it is OK. Looks like nowadays this library looks best from .NET perspective: github.com/VitaliiTsilnyk/NGettextMichelsen
S
0

There is nothing built in, we ended up coding something like this: Another solution can be:

use place holders like {CAR} in the resource file strings Maintain separate resource entries for singular and plural words for "car" : CAR_SINGULAR car
CAR_PLURAL cars

Develop a class with this logic:

class MyResource
 {

    private List<string> literals = new List<string>();
    public MyResource() { literals.Add("{CAR}") }
    public static string GetLocalizedString(string key,bool isPlural)
    {
       string val = rm.GetString(key);
       if(isPlural)
       {
          val = ReplaceLiteralWithPlural(val);
       }
       else
       {
          val = ReplaceLiteralWithSingular(val);   
       }     
    }  
}

string ReplaceLiteralWithPlural(string val)
{
   StringBuilder text = new StringBuilder(val)
   foreach(string literal in literals)
   {
      text = text.Replace(literal,GetPluralKey(literal));
   }
}

string GetPluralKey(string literal)
{
  return literal + "_PLURAL";
}
Severable answered 18/12, 2008 at 4:41 Comment(0)
F
0

This is still not possible in .NET natively. But it is a well known problem and already solved by gettext. It have native support for many technologies, even includes C# support. But looks like there is modern reimplementation now in .NET: https://github.com/VitaliiTsilnyk/NGettext

Frond answered 18/11, 2021 at 11:43 Comment(0)
T
-2

The logic needn't be in your view, but it's certainly not in the resource model the DotNet framework. Yours is a simple enough case that you can probably get away with creating a simple format string for singular, and one for plural. "You have 1 car."/"You have {0} cars." You then need to write a method that discriminates between the plural and singular case.

There are also a number of languages where there's no distinction between singular and plural, but this just requires a little duplication in the resource strings. (edit to add: gender and sometimes endings change depending on number of units in many languages, but this should be fine as long as you distinguish between singular and plural sentences, rather than just words).

Microsoft mostly gave up on semantically clever localization because it's hard to generalize even something like pluralization to 30+ languages. This is why you see such boring presentation of numeric quantities in most applications that are translated to many languages, along the lines of "Cars: {0}". That sounds lame, but surprisingly, the last time I checked, usability studies didn't actually favor the verbose natural language presentation in most cases.

Thimbleful answered 18/12, 2008 at 4:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.