Getting the user's region with navigator.language - javascript

For some time, I've been using something like this to get my user's country (ISO-3166):
const region = navigator.language.split('-')[1]; // 'US'
I've always assumed the string would be similar to en-US -- where the country would hold the 2nd position of the array.
I am thinking this assumption is incorrect. According to MDN docs, navigator.language returns: "string representing the language version as defined in BCP 47." Reading BCP 47, the primary language subtag is guaranteed to be first (e.g., 'en') but the region code is not guaranteed to be the 2nd subtag. There can be subtags that preceed and follow the region subtag.
For example "sr-Latn-RS" is a valid BCP 47 language tag:
sr | Latn | RS
primary language | script subtag | region subtag
Is the value returned from navigator.language a subset of BCP 47 containing only language and region? Or is there a library or regex that is commonly used to extract the region subtag from a language tag?

Your solution is based on the false premise that the browser's language tag reliably matches the user's country. E.g., I have set my browser language to German, even though I am living nowhere near Germany at the moment, but rather in the United States.
Also, for example in Chrome, many language packs do not require you to specify the region modifier. Setting Chrome's display language to German
provides the following language tag:
> navigator.language
< "de"
No region tag at all, and a fairly common language.
Bottom line is, my browser setup results in language tag de, even though I live in the United States.
A more accurate and possibly reliable way to determine the user's location would be to derive it from the IP address associated with the request. There are numerous services that offer this service. ip-api.com is one of them:
$.get("http://ip-api.com/json", function(response) {
console.log(response.country); // "United States"
console.log(response.countryCode); // "US"
}, "jsonp");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

You can now extract the region from a locale identifier using the Locale object in the Internationalization API.
const { region } = new Intl.Locale('sr-Latn-RS') // region => 'RS'
Note that this is not currently compatible with Internet Explorer.

Regex found here: https://github.com/gagle/node-bcp47/blob/master/lib/index.js
var re = /^(?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))$|^((?:[a-z]{2,3}(?:(?:-[a-z]{3}){1,3})?)|[a-z]{4}|[a-z]{5,8})(?:-([a-z]{4}))?(?:-([a-z]{2}|\d{3}))?((?:-(?:[\da-z]{5,8}|\d[\da-z]{3}))*)?((?:-[\da-wy-z](?:-[\da-z]{2,8})+)*)?(-x(?:-[\da-z]{1,8})+)?$|^(x(?:-[\da-z]{1,8})+)$/i;
let foo = re.exec('de-AT'); // German in Austria
let bar = re.exec('zh-Hans-CN'); // Simplified Chinese using Simplified script in mainland China
console.log(`region ${foo[5]}`); // 'region AT'
console.log(`region ${bar[5]}`); // 'region CN'

In Firefox, you can choose your language settings in preferences:
The list of languages has 269 items, 192 of which do not include any region code.
The region is only useful when a language has different variants depending on the location. This way users can tell the server in which language variant they prefer the response to be.
Do not use this approach to locate the user. It's too unreliable, because the user may not specify any region, or because the user could physically be in another place.
If you want to locate the user, you should use the Geolocation API.

Be careful you have navigator.language and navigator.languages.
langage :
console.log(navigator.language); // "fr"
langages :
console.log(navigator.languages); // ["fr", "fr-FR", "en-US", "en"]
To find countries see Wikipedia on ISO 3166-1 or use javascript lib :
i18n-iso-countries
country.js
ISO Country List - HTML select/dropdown snippet

Just as #TimoSta said,
Try this
$.getJSON('http://freegeoip.net/json/', function(result) {
alert(result.country_code);
});
from Get visitors language & country code with javascript (client-side). See answer of #noducks

The value you are receiving stems from the Accept-Language header of the HTTP request.
The values of the header can be quite complex like
Accept-Language: da, en-GB;q=0.8, en;q=0.7
As the name implies, the Accept-Language header basically defines acceptable languages, not countries.
A language tag may contain also additional location information, as in 'en-GB' but others like 'en' do not.
In case not, there is just no information about the country.
It is also not always possible to exactly map a language like 'en' to a country.
If the language is 'en', the country might be 'GB' but it may also be 'US'.
What you can do ;
Determine the country only, if the language contains one, as in 'en-GB'
If the language does not contain a country you have the following options :
A few languages are only used in one country, like 'da', danish which is spoken only in Denmark (I am guessing here), so you may map these cases.
You may use a default for other cases, depending on the language, e.g. map 'en' to 'GB'
You may use a general default like 'US' for all cases no country can be determined.
You can use additional information e.g. the clients IP address to determine the country
Finally you may ask the user to enter the country
I collected some additional information about the Accept-Language header here

Related

How to get ISO country code in google-libphonenumber Js package

I am creating new service, and need country ISO code based on mobile number. I am using google-libphonenumber package but in this package it giving information based on mobile and country ISO code.
I searched on google about this and offical npmjs site https://www.npmjs.com/package/google-libphonenumber but didn't get as per my requirement.
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
const number = phoneUtil.parseAndKeepRawInput('7358469469', 'IN');
const number = phoneUtil.parse('7358469469');
Expected result: I am expecting country ISO code based on mobile no.
Actual result: parseAndKeepRawInput and parse function expecting mobile and country ISO code to return detail information.
This is mission impossible, a phone number can be valid in various country. Phone number 7358469469 can be in India (+91-7358469469) or China (+86-7358469469) or any other countries.
However, if the phone number starts with +, you can parse the number and extract the country code, according to the country code specification. Please refer to https://countrycode.org/ for all countries' code list.
I was able to solve this problem by using the following code
const getRegionCodeForNumber = (number, defaultCountryCode = 'US') => {
const phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance()
const numberObj = phoneUtil.parseAndKeepRawInput(number, defaultCountryCode)
return phoneUtil.getRegionCodeForNumber(numberObj)
}
Calling it like this:
console.log(getRegionCodeForNumber('7358469469', 'IN'))
gives IN.
However #shaochuancs is right, to get something meaningful you'll need to pass the number in the international format starting with +, e.g.:
console.log(getRegionCodeForNumber('+86-7358469469', 'IN'))
gives CN.
The second parameter of getRegionCodeForNumber is default country code which the function will fall back to when the international country code with + is omitted.

Most compact URL encoding of JSON data?

Some time ago I saw a website that encoded game replay data into unicode characters so that you could copy-and-paste the address to share it with friends. I basically want to do the same thing -- I've got some data in a JavaScript object and I want to put it into the address bar.
I know I can use jQuery.param or something like that, but I want a much more compact format.
Turns out this is a little tricky to Google. Most search results turn up URL shorteners, which is distinctly different. I am not trying to store a short URL in my database for later lookup. All the data should be in the URL itself.
What encoding can I use for this? A link or description of the algorithm is fine, but impementations for Node/JavaScript would be even better.
I only need to support the latest version of Chrome stable, so I don't care if older browsers can't handle the unicode. I think I'll put the data in the fragment portion (after #) so I only need to support whatever encoding rules apply to that piece. I think just about anything is allowed, no?
There you go https://github.com/qntm/base65536 & https://www.npmjs.com/package/base65536
Base65536 is a binary encoding optimised for UTF-32-encoded text and Twitter. This JavaScript module, base65536, is the first implementation of this encoding.
It featured on hackernews some time ago.
Here's an implementation of enapupe's suggestion:
import Msgpack from 'msgpack-lite';
import Base65536 from 'base65536';
export function uniencode(obj) {
return Base65536.encode(Msgpack.encode(obj));
}
export function unidecode(str) {
return Msgpack.decode(Base65536.decode(str));
}
Usage:
let o = {foo:'bar',baz:[1,2,3,4,5],quux:'corge'};
console.log(uniencode(o).length,JSON.stringify(o).length); // 24, 46
i.e. uniencode is about half the length of JSON.stringify, or even less according to Twitter (.length doesn't count unicode properly. Twitter counts the above as 15 chars). A better measurement is:
function len(str) {
return [...str].length;
}
Which gives 15 and 46 respectively.

Odd behaviour in Google Web Speech API

I'm working with Google's Web Speech API using Google Chrome (55.0.2883.87) and I'm experiencing some very weird behaviour.
When attempting to speak out names, followed by a number (like John 4) it usually just speaks out the name and the number, as it should - but for some names it puts the word chapter between the name and the number, so Daniel 4 becomes Daniel Chapter 4.
I have picked up some random names and tested them with the following code:
<script>
var names = ['Brian', 'John', 'Mike', 'Julia', 'Daniel', 'Michael', 'David', 'Jason', 'Jack'];
names.forEach(function(name) {
var msg = new SpeechSynthesisUtterance(name + ' 4');
window.speechSynthesis.speak(msg);
});
</script>
The msg variable doesn't include the word chapter when logging it with console.log()
Of these 9 names, the names John and Daniel are spoken with the word chapter between them.
Question
Why does this happen, and which criteria determines which names are affected?
I think that one of your homonyms wrote something in a famous book, and a certain John did too. I would guess that it does the same for Jeremiah or these others.
But I can't repro neither on my 55.0.2883.95 nor on my 57.0.2954.0 on mac...
Maybe it was a Christmas Easter egg.
so many religious parts in this answer...
I do not think that this is an "Easter Egg":
Generally, speech synthesis engines often try to interpret text fragments in some meaningful way, e.g. reading numbers with punctuation as dates, if that fragment "looks" like a date.
Explanation
With Google, I would guess that they heavily rely on statistics for deciding, if a text fragment should be interpreted one way or the other.
In practice this may fail for specific cases, for several reasons: e.g. if the specific case really is some specialized case; if there is not enough "context" to derive the correct/intended meaning (this may be especially true for very short sentences/fragments); if the (text) corpus for deriving the statistics is not balanced w.r.t. common use...
Suggestion
Depending on the engine, the behavior often can be somewhat controlled, by formatting the input text differently.
E.g. testing your code snippet in Chrome: if you write out the number ("four" instead of 4), or insert a comma after the name (i.e.name + ', 4'), then the speech engine will not insert "chapter" (note that comma also introduces a short pause).

jQuery Globalization. Pass currency unit as argument for C format

I am setting up a multilingual site that deals with currencies. I want to be able to display correct currency formats based on the selected language. The server side PHP stuff is a doddle. Using a combination of PHPs NumberFormatter and strftime I have been able to format currencies and dates correctly.
There is however a requirement to have the same degree of formatting done client side with javascript.
I have come across Globalization (former jQuery plugin) and it looks quite promising.
If I want to display a dollar value in American English I can do something like this:
jQuery.preferCulture("en-US");
// Formatting price
var price = jQuery.format(3899.888, "c");
//Assigning stock price to the control
jQuery("#price").html(price);
and this will output:
$3,899.89
While doing:
jQuery.preferCulture("fr-FR");
// Formatting price
var price = jQuery.format(3899.888, "c");
//Assigning stock price to the control
jQuery("#price").html(price);
outputs:
3 899,89 €
which looks perfect. however, I have a need to output multiple currencies. So, if I have 'fr-FR' selected as my preferred culture, how can I output, say, a dollar value like so:
3 899,89 $
so that the format is French, but the value is American Dollar. I have looked but not found anyway to pass a currency symbol as an argument.
The only documented way to modify the currency symbol in Globalize is to change the numberFormat.currency.symbol property of a given culture—in this case, the fr-FR culture. This will kind of do what you want, but it’s not a very elegant solution, and you would need to manually build a table of correct symbols for each locale and write another method to swap them out. (n.b. It is possible to pass a third argument to Globalize.format with a different locale identifier, but this just formats the number using that locale’s cultural settings.) Looking at the culture definition syntax, there is simply no provision for displaying different currencies using a given locale.
If you were to look elsewhere, the dojo/currency module in the Dojo Toolkit does do exactly what you need, using data from the Unicode Common Locale Data Repository to determine how to represent various currencies in different locales. So you can set your locale to fr, write currency.format(3899.888, { currency: "USD" }), and it will output the currency in USD in the correct format for the French locale.
I had the same problem, in the end I just replaced the default currency symbol on the output with the symbol I wanted to display. It's a bit primitive but it keeps the formatting correct for the locale with the currency symbol you want.
function formatCurrency(value, format, symbol){
var formattedValue = Globalize.format(value, format);
if (typeof symbol === "string") {
formattedValue = formattedValue.replace(Globalize.culture().numberFormat.currency.symbol, symbol);
}
return formattedValue;
}
document.getElementById("price1").innerHTML = formatCurrency(123.34,"c"); //<-- $123.34
document.getElementById("price2").innerHTML = formatCurrency(123.34,"c","£"); //<-- £123.34
Here is the fiddle

Numbers localization in Web applications

How can I set the variant of Arabic numeral without changing character codes?
Eastern Arabic ۰ ۱ ۲ ۳ ٦ ٥ ٤ ۷ ۸ ۹
Persian variant ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹
Western Arabic 0 1 2 3 4 5 6 7 8 9
(And other numeral systems)
Here is a sample code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div lang="fa">0123456789</div>
<div lang="ar">0123456789</div>
<div lang="en">0123456789</div>
</body>
</html>
How can I do this using only client-side technologies (HTML,CSS,JS)?
The solution should have no negative impact on page's SEO score.
Note that in Windows text boxes (e.g. Run) numbers are displayed correctly according to language of surrounding text.
See also: Numbers localization in desktop applications
Note: Localisation of numbers are super easy on backend using this PHP package https://github.com/salarmehr/cosmopolitan
Here is an approach with code shifting:
// Eastern Arabic (officially "Arabic-Indic digits")
"0123456789".replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x0630);
}); // "٠١٢٣٤٥٦٧٨٩"
// Persian variant (officially "Eastern Arabic-Indic digits (Persian and Urdu)")
"0123456789".replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x06C0);
}); // "۰۱۲۳۴۵۶۷۸۹"
DEMO: http://jsfiddle.net/bKEbR/
Here we use Unicode shift, since numerals in any Unicode group are placed in the same order as in latin group (i.e. [0x0030 ... 0x0039]). So, for example, for Arabic-Indic group shift is 0x0630.
Note, it is difficult for me to distinguish Eastern characters, so if I've made a mistake (there are many different groups of Eastern characters in Unicode), you could always calculate the shift using any online Unicode table. You may use either official Unicode Character Code Charts, or Unicode Online Chartable.
One has to decide if this is a question of appearance or of transformation. One must also decide if this is a question involving character-level semantics or numeral representations. Here are my thoughts:
The question would have entirely different semantics, if we had a situation where Unicode had not sparated out the codes for numeric characters.
Then, displaying the different glyphs as appropriate would simply be a matter of using the appropriate font. On the other hand, it would not have been possible to simply write out the different characters as I did below without changing fonts. (The situation is not exactly perfect as fonts do not necessarily cover the whole range of the 16-bit Unicode set, let alone the 32-bit Unicode set.)
9, ٩ (Arabic), ۹ (Urdu), 玖 (Chinese, complex), ๙ (Thai), ௯ (Tamil) etc.
Now, assuming we accept Unicode semantics i.e. that '9' ,'٩', and '۹' are distinct characters, we may conclude that the question is not about appearance (something that would have been in the purview of CSS), but of transformation -- a few thoughts about this later, for now let us assume this is the case.
When focusing on character-level semantics, the situation is not too dissimilar with what happens with alphabets and letters. For instance, Greek 'α' and Latin 'a' are considered distinct, even though the Latin alphabet is nearly identical to the Greek alphabet used in Euboea. Perhaps even more dramatically, the corresponding capital variants, 'Α' (Greek) and 'A' (Latin) are visually identical in practically all fonts supporting both scripts, yet distinct as far as Unicode is concerned.
Having stated the ground rules, let us see how the question can be answered by ignoring them, and in particular ignoring (character-level) Unicode semantics.
(Horrible, nasty and non-backwards compatible) Solution: Use fonts that map '0' to '9' to the desired glyphs. I am not aware of any such fonts. You would have to use #font-face and some font that has been appropriately hacked to do what you want.
Needless to say, I am not particularly fond of this solution. However, it is the only simple solution I am aware of that does what the question asks "without changing character codes" on either the server or the client side. (Technically speaking the Cufon solution I propose below does not change the character codes either, but what it does, drawing text into canvases is vastly more complex and also requires tweaking open-source code).
Note: Any transformational solution i.e. any solution that changes the DOM and replaces characters in the range '0' to '9' to, say, their Arabic equivalents will break code that expects numerals to appear in their original form in the DOM. This problem is, of course, worst when discussing forms and inputs.
An example of an answer taking the transformational approach is would be:
$("[lang='fa']").find("*").andSelf().contents().each(function() {
if (this.nodeType === 3)
{
this.nodeValue = this.nodeValue.replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x0630);
});
}
});
Note: Code taken from VisioN's second jsFiddle. If this is the only part of this answer that you like, make sure you upvote VisioN's answer, not mine!!! :-)
This has two problems:
It messes with the DOM and as a result may break code that used to work assuming it would find numerals in the "standard" form (using digits '0' to '9'). See the problem here: http://jsfiddle.net/bKEbR/10/ For instance, if you had a field containing the sum of some integers the user inputs, you might be in for a surprise when you try to get its value...
It does not address the issue of what goes on inside input (and textarea) elements. If an input field is initialised with, say, "42", it will retail that value. This can be fixed easily, but then there is the issue of actual input... One may decide to change characters as they come, convert the values when they changes and so on and so forth. If such conversion is made then both the client side and the server side will need to be prepared to deal with different kinds of numeral. What comes out of the box in Javascript, jQuery and even Globalize (client-side), and ASP.NET, PHP etc. (server-side) will break if fed with numerals in non-standard formats ...
A slightly more comprehensive solution (taking care also of input/textarea elements, both their initial values and user input) might be:
//before the DOM change, test1 holds a numeral parseInt can understand
alert("Before: test holds the value:" +parseInt($("#test1").text()));
function convertNumChar(c) {
return String.fromCharCode(c.charCodeAt(0) + 0x0630);
}
function convertNumStr(s) {
return s.replace(/\d/g, convertNumChar);
}
//the change in the DOM
$("[lang='fa']").find("*").andSelf().contents()
.each(function() {
if (this.nodeType === 3)
this.nodeValue = convertNumStr(this.nodeValue);
})
.filter("input:text,textarea")
.each(function() {
this.value = convertNumStr(this.value)
})
.change(function () {this.value = convertNumStr(this.value)});
//test1 now holds a numeral parseInt cannot understand
alert("After: test holds the value:" +parseInt($("#test1").text()))
The entire jsFiddle can be found here: http://jsfiddle.net/bKEbR/13/
Needless to say, this only solves the aforementioned problems partially. Client-side and/or server-side code will have to recognise the non-standard numerals and convert them appropriately either to the standard format or to their actual values.
This is not a simple matter that a few lines of javascript will solve. And this is but the simplest case of such possible conversion since there is a simple character-to-character mapping that needs to be applied to go from one form of numeral to the other.
Another go at an appearance-based approach:
Cufon-based Solution (Overkill, Non-Backwards Compatible (requires canvas), etc.): One could relatively easily tweak a library like Cufon to do what is envisaged. Cufon can do its thing and draw glyphs on a canvas object, except that the tweak will ensure that when elements have a certain property, the desired glyphs will be used instead of the ones normally chosen. Cufon and other libraries of the kind tend to add elements to the DOM and alter the appearance of existing elements but not touch their text, so the problems with the transformational approaches should not apply. In fact it is interesting to note that while (tweaked) Cufon provides a clearly transformational apprroach as far as the overall DOM is concerned, it is an appearance-based solution as far as its mentality goes; I would call it a hybrid solution.
Alternative Hybrid-Solution: Create new DOM elements with the arabic content, hide the old elements but leave their ids and content intact. Synchronize the arabic content elements with their corresponding, hidden, elements.
Let's try to think outside the box (the box being current web standards).
The fact that certain characters are unique does not mean they are unrelated. Moreover, it does not necessarily mean that their difference is one of appearance. For instance, 'a' and 'A' are the same letter; in some contexts they are considered to be the same and in others to be different. Having, the distinction in Unicode (and ASCII and ISO-Latin-1 etc. before it) means that some effort is required to overcome it.
CSS offers a quick and easy way for changing the case of letters. For instance, body {text-transform:uppercase} would turn all letters in the text in the body of the page into upper case. Note that this is also a case of appearance-change rather than transformation: the DOM of the body element does not change, just the way it is rendered.
Note: If CSS supported something like numerals-transform: 'ar' that would probably have been the ideal answer to the question as it was phrased.
However, before we rush to tell the CSS committee to add this feature, we may want to consider what that would mean. Here, we are tackling a tiny little problem, but they have to deal with the big picture.
Output:
Would this numerals-transform feature work allow '10' (2-characters) to appear as 十(Chinese, simple), 拾 (Chinese, complex), X (Latin) (all 1-character) and so on if instead of 'ar', the appropriate arguments were given?
Input:
Would this numerals-transform feature change '十'(Chinese, simple) into its Arabic equivalent, or would it simply target '10'? Would it somehow cleverly detect that "MMXI" (Latin numeral for 2012) is a number and not a word and convert it accordingly?
The question of number representation is not as simple as one might imagine just looking at this question.
So, where does all this leave us:
There is no simple presentation-based solution. If one appears in the future, it will not be backwards compatible.
There can be a transformational "solution" here and now, but even if this is made to work also with form elements as I have done (http://jsfiddle.net/bKEbR/13/) there need to be server-side and client-side awareness of the non-standard format used.
There may be complex hybrid solutions. They are complex but offer some of the advantages of the presentation-based approaches in some cases.
A CSS solution would be nice, but actually the problem is big and complex when one looks at the big picture which involves other numeric systems (with less trivial conversions from and to the standard system), decimal points,signs etc.
At the end of the day, the solution I see as realistic and backwards compatible would be an extension of Globalize (and server-side equivalents) possibly with some additional code to take care of user input. The idea is that this is not a problem at the character-level (because once you consider the big picture it is not) and that it will have to be treated in the same way that differences with thousands and decimal separators have been dealt with: as formatting/parsing issues.
I imagine the best way is to use a regexp to search what numeric characters should be changed via adding a class name to the div that needs a different numeric set.
You can do this using jQuery fairly easy.
jsfiddle DEMO
EDIT: And if you don't want to use a variable, then see this revised demo:
jsfiddle DEMO 2
I have been working on a general web page localization technique that does more than just numbers (its similar to .po files)
The localization files are simple (the strings can contain html if needed)
/* Localization file - save as document_url.lang.js ... index.html.en.js: */
items=[
{"id":"string1","value":"Localized text of string1 here."},
{"id":"string2", "value":"۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ "}
];
rtl=false; /* set to true for rtl languages */
This format is useful to separate out for translators (or mechanical turk)
and a basic page template
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head><title>My title</title>
<style>.txt{float:left;margin-left:10px}</style>
</head>
<body onload='setLang()'>
<div id="string1" class="txt">This is the default text of string1.</div>
<div id="string2" class="txt">0 1 2 3 4 5 6 7 8 9 </div>
</body></html>
<script>
function setLang(){
for(var i=0;i<items.length;i++){
term=document.getElementById(items[i].id)
if(term)term.innerHTML=items[i].value
if(rtl){ /* for rtl languages */
term.style.styleFloat="right"
term.style.cssFloat="right"
term.style.textAlign="right"
}
}
}
var lang=navigator.userLanguage || navigator.language;
var script=document.createElement("script");
script.src=document.URL+"-"+lang.substring(0,2)+".js"
var head = document.getElementsByTagName('head')[0]
head.insertBefore(script,head.firstChild)
</script>
I tried to keep it pretty simple, yet cover as many locales as possible so additional css is likely required (I have to admit a lack of exposure to rtl languages, so many more styles may need to be set)
I do have font checking code that would be useful if you know what fonts support your character codes well
function hasFont(f){
var s=document.createElement("span")
s.style.fontSize="72px"
s.innerHTML="MWMWM"
s.style.visibility="hidden"
s.style.fontFamily=[(f=="monospace")?'':'monospace','sans-serif','serif']
document.body.appendChild(s)
var w=s.offsetWidth
s.style.fontFamily=[f,'monospace','sans-serif','serif']
document.body.lastChild=s
return s.offsetWidth!=w
}
usage: if(hasFont("myfont"))myelement.style.fontFamily="myfont"
A new (to date) and simple JS solution would be to use Intl.NumberFormat. It supports numeral localization, formatting variations as well as local currencies (see documentation for more examples).
To use an example very similar to MDN's own:
const val = 1234567809;
console.log('Eastern Arabic (Arabic-Egyptian)', new Intl.NumberFormat('ar-EG').format(val));
console.log('Persian variant (Farsi)',new Intl.NumberFormat('fa').format(val));
console.log('English (US)',new Intl.NumberFormat('en-US').format(val));
Intl.NumberFormat also seems to support string numeric values as well as indicates when it's not a number in the local language.
const val1 = '456';
const val2 = 'Numeric + string example, 123';
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val1));
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val2));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val1));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val2));
console.log('English',new Intl.NumberFormat('en-US').format(val1));
console.log('English', new Intl.NumberFormat('en-US').format(val2));
For the locale identifier (string passed to NumberFormat constructor indicating locale), I experimented with the values above and they seemed fine. I tried finding a list for all possible values, and through MDN came across this documentation and this list that could be helpful.
I'm not familiar with SEO, and am thus unsure how this answers that part of the question.
you can try this:
This is CSS source code:
#font-face
{
font-family: A1Tahoma;
src: url(yourfont.eot) format('eot')
, url(yourfont.ttf) format('truetype')
, url(yourfont.woff) format('woff')
, url(yourfont.svg) format('svg');
}
p{font-family:A1Tahoma; font-size:30px;}
And this is HTML code:
<p>سلام به همه</p>
<p>1234567890</p>
And finally you will see your result.remember that 4 font types use for any browser such as IE,FIREFOX and so on.
"salam reza ,to mituni in karo anjam bedi ta un fonte dekhaheto be site ezafe koni."
I have created a jquery plugin that can convert Western Arabic numbers to Eastern ones (Persian only). But it can be extended to convert a number to any desired numeral system. My jQuery plugin has two advantages:
Detect and convert numbers properly in child nodes.
Detect and convert point characters appropriately.
You can clone this plugin from github.
My plugin code:
(function( $ ){
$.fn.persiaNumber = function() {
var groupSelection = this;
for(i=0; i< groupSelection.length ; i++){
var htmlTxt = $(groupSelection[i]).html();
var trueTxt = convertDecimalPoint(htmlTxt);
trueTxt = convertToPersianNum(trueTxt);
$(groupSelection[i]).html(trueTxt);
}
function convertToPersianNum(htmlTxt){
var otIndex = htmlTxt.indexOf("<");
var ctIndex = htmlTxt.indexOf(">");
if(otIndex == -1 && ctIndex == -1 && htmlTxt.length > 0){
var trueTxt = htmlTxt.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
return trueTxt;
}
var tag = htmlTxt.substring(otIndex,ctIndex + 1);
var str = htmlTxt.substring(0,otIndex);
str = convertDecimalPoint(str);
str = str.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
var refinedHtmlTxt = str + tag;
var htmlTxt = htmlTxt.substring(ctIndex + 1, htmlTxt.length);
if(htmlTxt.length > 0 && otIndex != -1 || ctIndex != -1){
var trueTxt = refinedHtmlTxt;
var trueTxt = trueTxt + convertToPersianNum(htmlTxt);
}else{
return refinedHtmlTxt+ htmlTxt;
}
return trueTxt;
}
function convertDecimalPoint(str){
for(j=1;j<str.length - 1; j++){
if(str.charCodeAt(j-1) > 47 && str.charCodeAt(j-1) < 58 && str.charCodeAt(j+1) > 47 && str.charCodeAt(j+1) < 58 && str.charCodeAt(j) == 46)
str = str.substring(0,j) + '٫' + str.substring(j+1,str.length);
}
return str;
}
};
})( jQuery );
http://jsfiddle.net/VPWmq/2/
You can convert numbers in this way:
const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
const number = 44653420;
convertedNumber = String(number).replace(/\d/g, function(digit) {
return persianDigits[digit]
})
console.log(convertedNumber) // ۴۴۶۵۳۴۲۰
If anyone is looking for localizing into Bangla numbers using this code shifting method:
$("[lang='bang']").text(function(i, val) {
return val.replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x09B6);
});
});
You can also visit here to see the UNICODE of ASCII Hexadecimal codes of Bangla

Categories

Resources