intl/locale/src/PluralForm.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 this.EXPORTED_SYMBOLS = [ "PluralForm" ];
michael@0 6
michael@0 7 /**
michael@0 8 * This module provides the PluralForm object which contains a method to figure
michael@0 9 * out which plural form of a word to use for a given number based on the
michael@0 10 * current localization. There is also a makeGetter method that creates a get
michael@0 11 * function for the desired plural rule. This is useful for extensions that
michael@0 12 * specify their own plural rule instead of relying on the browser default.
michael@0 13 * (I.e., the extension hasn't been localized to the browser's locale.)
michael@0 14 *
michael@0 15 * See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
michael@0 16 *
michael@0 17 * List of methods:
michael@0 18 *
michael@0 19 * string pluralForm
michael@0 20 * get(int aNum, string aWords)
michael@0 21 *
michael@0 22 * int numForms
michael@0 23 * numForms()
michael@0 24 *
michael@0 25 * [string pluralForm get(int aNum, string aWords), int numForms numForms()]
michael@0 26 * makeGetter(int aRuleNum)
michael@0 27 * Note: Basically, makeGetter returns 2 functions that do "get" and "numForm"
michael@0 28 */
michael@0 29
michael@0 30 const Cc = Components.classes;
michael@0 31 const Ci = Components.interfaces;
michael@0 32
michael@0 33 const kIntlProperties = "chrome://global/locale/intl.properties";
michael@0 34
michael@0 35 // These are the available plural functions that give the appropriate index
michael@0 36 // based on the plural rule number specified. The first element is the number
michael@0 37 // of plural forms and the second is the function to figure out the index.
michael@0 38 let gFunctions = [
michael@0 39 // 0: Chinese
michael@0 40 [1, function(n) 0],
michael@0 41 // 1: English
michael@0 42 [2, function(n) n!=1?1:0],
michael@0 43 // 2: French
michael@0 44 [2, function(n) n>1?1:0],
michael@0 45 // 3: Latvian
michael@0 46 [3, function(n) n%10==1&&n%100!=11?1:n!=0?2:0],
michael@0 47 // 4: Scottish Gaelic
michael@0 48 [4, function(n) n==1||n==11?0:n==2||n==12?1:n>0&&n<20?2:3],
michael@0 49 // 5: Romanian
michael@0 50 [3, function(n) n==1?0:n==0||n%100>0&&n%100<20?1:2],
michael@0 51 // 6: Lithuanian
michael@0 52 [3, function(n) n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?2:1],
michael@0 53 // 7: Russian
michael@0 54 [3, function(n) n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2],
michael@0 55 // 8: Slovak
michael@0 56 [3, function(n) n==1?0:n>=2&&n<=4?1:2],
michael@0 57 // 9: Polish
michael@0 58 [3, function(n) n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2],
michael@0 59 // 10: Slovenian
michael@0 60 [4, function(n) n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3],
michael@0 61 // 11: Irish Gaeilge
michael@0 62 [5, function(n) n==1?0:n==2?1:n>=3&&n<=6?2:n>=7&&n<=10?3:4],
michael@0 63 // 12: Arabic
michael@0 64 [6, function(n) n==0?5:n==1?0:n==2?1:n%100>=3&&n%100<=10?2:n%100>=11&&n%100<=99?3:4],
michael@0 65 // 13: Maltese
michael@0 66 [4, function(n) n==1?0:n==0||n%100>0&&n%100<=10?1:n%100>10&&n%100<20?2:3],
michael@0 67 // 14: Macedonian
michael@0 68 [3, function(n) n%10==1?0:n%10==2?1:2],
michael@0 69 // 15: Icelandic
michael@0 70 [2, function(n) n%10==1&&n%100!=11?0:1],
michael@0 71 // 16: Breton
michael@0 72 [5, function(n) n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?0:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?1:(n%10==3||n%10==4||n%10==9)&&n%100!=13&&n%100!=14&&n%100!=19&&n%100!=73&&n%100!=74&&n%100!=79&&n%100!=93&&n%100!=94&&n%100!=99?2:n%1000000==0&&n!=0?3:4],
michael@0 73 ];
michael@0 74
michael@0 75 this.PluralForm = {
michael@0 76 /**
michael@0 77 * Get the correct plural form of a word based on the number
michael@0 78 *
michael@0 79 * @param aNum
michael@0 80 * The number to decide which plural form to use
michael@0 81 * @param aWords
michael@0 82 * A semi-colon (;) separated string of words to pick the plural form
michael@0 83 * @return The appropriate plural form of the word
michael@0 84 */
michael@0 85 get get()
michael@0 86 {
michael@0 87 // This method will lazily load to avoid perf when it is first needed and
michael@0 88 // creates getPluralForm function. The function it creates is based on the
michael@0 89 // value of pluralRule specified in the intl stringbundle.
michael@0 90 // See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
michael@0 91
michael@0 92 // Delete the getters to be overwritten
michael@0 93 delete PluralForm.numForms;
michael@0 94 delete PluralForm.get;
michael@0 95
michael@0 96 // Get the plural rule number from the intl stringbundle
michael@0 97 let ruleNum = Number(Cc["@mozilla.org/intl/stringbundle;1"].
michael@0 98 getService(Ci.nsIStringBundleService).createBundle(kIntlProperties).
michael@0 99 GetStringFromName("pluralRule"));
michael@0 100
michael@0 101 // Make the plural form get function and set it as the default get
michael@0 102 [PluralForm.get, PluralForm.numForms] = PluralForm.makeGetter(ruleNum);
michael@0 103 return PluralForm.get;
michael@0 104 },
michael@0 105
michael@0 106 /**
michael@0 107 * Create a pair of plural form functions for the given plural rule number.
michael@0 108 *
michael@0 109 * @param aRuleNum
michael@0 110 * The plural rule number to create functions
michael@0 111 * @return A pair: [function that gets the right plural form,
michael@0 112 * function that returns the number of plural forms]
michael@0 113 */
michael@0 114 makeGetter: function(aRuleNum)
michael@0 115 {
michael@0 116 // Default to "all plural" if the value is out of bounds or invalid
michael@0 117 if (aRuleNum < 0 || aRuleNum >= gFunctions.length || isNaN(aRuleNum)) {
michael@0 118 log(["Invalid rule number: ", aRuleNum, " -- defaulting to 0"]);
michael@0 119 aRuleNum = 0;
michael@0 120 }
michael@0 121
michael@0 122 // Get the desired pluralRule function
michael@0 123 let [numForms, pluralFunc] = gFunctions[aRuleNum];
michael@0 124
michael@0 125 // Return functions that give 1) the number of forms and 2) gets the right
michael@0 126 // plural form
michael@0 127 return [function(aNum, aWords) {
michael@0 128 // Figure out which index to use for the semi-colon separated words
michael@0 129 let index = pluralFunc(aNum ? Number(aNum) : 0);
michael@0 130 let words = aWords ? aWords.split(/;/) : [""];
michael@0 131
michael@0 132 // Explicitly check bounds to avoid strict warnings
michael@0 133 let ret = index < words.length ? words[index] : undefined;
michael@0 134
michael@0 135 // Check for array out of bounds or empty strings
michael@0 136 if ((ret == undefined) || (ret == "")) {
michael@0 137 // Report the caller to help figure out who is causing badness
michael@0 138 let caller = PluralForm.get.caller ? PluralForm.get.caller.name : "top";
michael@0 139
michael@0 140 // Display a message in the error console
michael@0 141 log(["Index #", index, " of '", aWords, "' for value ", aNum,
michael@0 142 " is invalid -- plural rule #", aRuleNum, "; called by ", caller]);
michael@0 143
michael@0 144 // Default to the first entry (which might be empty, but not undefined)
michael@0 145 ret = words[0];
michael@0 146 }
michael@0 147
michael@0 148 return ret;
michael@0 149 }, function() numForms];
michael@0 150 },
michael@0 151
michael@0 152 /**
michael@0 153 * Get the number of forms for the current plural rule
michael@0 154 *
michael@0 155 * @return The number of forms
michael@0 156 */
michael@0 157 get numForms()
michael@0 158 {
michael@0 159 // We lazily load numForms, so trigger the init logic with get()
michael@0 160 PluralForm.get();
michael@0 161 return PluralForm.numForms;
michael@0 162 },
michael@0 163 };
michael@0 164
michael@0 165 /**
michael@0 166 * Private helper function to log errors to the error console and command line
michael@0 167 *
michael@0 168 * @param aMsg
michael@0 169 * Error message to log or an array of strings to concat
michael@0 170 */
michael@0 171 function log(aMsg)
michael@0 172 {
michael@0 173 let msg = "PluralForm.jsm: " + (aMsg.join ? aMsg.join("") : aMsg);
michael@0 174 Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).
michael@0 175 logStringMessage(msg);
michael@0 176 dump(msg + "\n");
michael@0 177 }

mercurial