PHP Locale get country code - php

I am currently getting a user's country in PHP using the following method;
Locale::getDisplayRegion($_SERVER[HTTP_ACCEPT_LANGUAGE],'en')
This returns the countries name in text e.g. United States.
However, I want to return the abbreviated country code from the $_SERVER[HTTP_ACCEPT_LANGUAGE] request rather than the full text name. How can I do this?

The Symfony framework has a handy function for determining the preferred language based on the Accept-Language header:
https://github.com/symfony/HttpFoundation/blob/master/Request.php#L1463
https://github.com/symfony/HttpFoundation/blob/master/Request.php#L1498

Depending on how you want to use the abbreviated country code, you can use something as such.
$country = substr(locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']), -2);
This will result in producing "xx" in for the variable resulting in country code.

Related

Algolia highlighting in Laravel 5.3

I am using Laravel 5.3 and Algolia,
I want to highlight the search result,I read the documentation but I still don't know how to do it.
https://www.algolia.com/doc/api-client/php/parameters#attributestohighlight
Any ideas?
When search results are returned from Algolia, they will wrap the "highlighted part" with <em> </em> tags by default. This happens right out of the box, so all you really need to do is use CSS to customize the look of <em>s within your search results div to get the effect you want.
Of course if you prefer that they wrap highlighted text in something other than <em> then you can customize it with anything you wish (such as maybe a span tag with a "highlighted-search" class or something). You customize this when initializing the search in your PHP.
$index = $client->initIndex('contacts');
$result = $index->search('search query', ['attributesToRetrieve' => 'firstname,lastname', 'hitsPerPage' => 50, 'highlightPreTag' => '<span class="highlighted-search">', 'highlightPostTag' => '</span>']);
Now let's say you search 'John D' and submit that search query. Algolia will return a string to the effect of:
<span class="highlighted-search">John D</span>oe
Now with your CSS you customize it like
span.highlighted-search {
background-color:yellow;
}
and now it will highlight the search query with yellow.
Of course this is all assuming you want the static (PHP Library) server side search results. I highly recommend that you use the autocomplete.js library so you can get live search results as you type. This requires using the js libraries to return results client-side while the user types. It is a much better experience.
In each item returned by the search engine, there is an extra "_highlightResult" attribute that contains some metadata and the value of the searchable attributes modified with search terms surrounded with <em>.
For instance, for the search term "toux", the returned JSON will looks like:
{
"medicament" : "VICKS TOUX SECHE 7,33 mg ADULTES MIEL, pastille",
"_highlightResult" : {
"medicament" : {
"value" : "VICKS <em>TOUX</em> SECHE 7,33 mg ADULTES MIEL, pastille",
"matchedWords" : ["toux"]
....
...
}
To highlight the search results, with the search terms, you simply have to display the attribute value under "_highlightResult" instead of the raw one.
If you are not using it already, I would recommend you to use Instantsearch.js.
Highlighting the typed keywords of the search results is dealt whitin the hits widget the same way, in its templates.item parameter.
You may find live code example of this feature here https://community.algolia.com/instantsearch.js/examples/

How to use ipinfodb to find country code only

I want to find the country code of my site visitor using the ipinfodb API.
When I try the following, http://api.ipinfodb.com/v3/ip-country/?key=<My_API_Key>&ip=<Some_IP>, it gives the following output:
OK;;<Some_IP>;US;UNITED STATES
How do I filter this output so that it shows only the country code ?
Regards,
Timothy
EDIT:
In reply to Charles,
After searching on google I came to know that the API can be given a 'format attribute as XML' so the following works.
$xml = simplexml_load_file('http://api.ipinfodb.com/v3/ip-country/?key=<My_API>&format=xml&ip=<Some_IP>);
echo $xml->countryCode;
How can I get the same output without the XML argument ?
Thanks
OK;;<Some_IP>;US;UNITED STATES
How do I filter this output so that it shows only the country code ?
I find it curious that you'd be able to invoke SimpleXML, but didn't think of explode, which will turn a string in into an array, splitting on the given delimiter. In this case, we need to explode on ;:
$string_data = 'OK;;127.0.0.1;US;UNITED STATES';
$sploded_data = explode(';', $string_data);
print_r($sploded_data);
echo "\nCountry code: ", $sploded_data[3], "\n";
This should emit:
Array
(
[0] => OK
[1] =>
[2] => 127.0.0.1
[3] => US
[4] => UNITED STATES
)
Country code: US
You may wish to review the rest of the string manipulation functions to see if there's any other interesting things you may have missed.
The above answer isn't particularly helpful, because the server output is only static if you explicitly specify the same IP address every time. If you hardcode a location request for a particular IP address, it's going to the be the same every time. What's the point?
Do this instead
Install the PHP class for their API. PHP Class
Play around with the PHP sample found here; save it as its own webpage and observe the results. Let's call it "userlocation.php." Please note that the fields will be null if you load from localhost.
Okay, the trick to parse this output is array_values(). Took me forever to figure this, but eventually I stumbled upon this.
So...
$locations = array_values($locations);
echo $locations[n],"<br />\n";
echo $locations[n+1],"<br />\n";
etc.
Whatever element you need, you can get in this way -- and it's dynamic. The code will return whatever country pertains to the user's IP address.
One last note. Take care to paste your API key into the class file and not into userlocation.php. The class file variables are protected, which is a good thing.
Anyway, I'm no expert; just thought I'd share what I've learned.

php extract UK postal code and validate it

I have some text blocks like
John+and+Co-Accountants-Hove-BN31GE-2959519
I need a function to extract the postcode "BN31GE". It may happen to not exist and have a text block without postcode so the function must also validate if the extracted text is valid postcode .
John+and+Co-Accountants-Hove-2959519
The UK Government Data Standard for postcodes is:
((GIR 0AA)|((([A-PR-UWYZ][0-9][0-9]?)|(([A-PR-UWYZ][A-HK-Y][0-9][0-9]?)|(([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY])))) [0-9][ABD-HJLNP-UW-Z]{2}))
Edit: I had the above in some (personal) code with a reference to a now non-existence UK government web page. The appropriate British Standard is BS7666 and information on this is currently available here. That lists a slightly different regex.
Find below code to extract valid UK postal code. It return array if post code found otherwise empty.
<?php
$getPostcode="";
$str="John+and+Co-Accountants-Hove-BN31GE-2959519";
$getArray = explode("-",$str);
if(is_array($getArray) && count($getArray)>0) {
foreach($getArray as $key=>$val) {
if(preg_match("/^(([A-PR-UW-Z]{1}[A-IK-Y]?)([0-9]?[A-HJKS-UW]?[ABEHMNPRVWXY]?|[0-9]?[0-9]?))\s?([0-9]{1}[ABD-HJLNP-UW-Z]{2})$/i",strtoupper($val),$postcode)) {
$getPostcode = $postcode[0];
}
}
}
print"<pre>";
print_r($getPostcode);
?>
Use a regex: preg_grep function,
I don't know the format of english postcodes but you could go with something like:
(-[a-zA-Z0-9]+-)+
This matches
"-Accountants-"
"-BN31GE-"
You can then proceed at taking always the second value or you can enhance you regex to match exactly english postcodes, something like maybe
([A-Z0-9]{6})

How to convert a country string to its ISO 3166-1 code using Zend?

Does anybody know if it's possible to use Zend_Locale to get the ISO 3166-1 code for a country if you have the country name as a string?
For example I have "Nederland" so I would like to get "NL".
I don't know if Zend has something for that, but it's fairly easy to do on your own.
This tutorial shows how you can grab the latest list of ISO 3166-1 country codes in XML format, parse it, and then create a PHP file that can be included when you need a country code translation array:
$str = file_get_contents('http://opencountrycodes.appspot.com/xml/');
$xml = new SimpleXMLElement($str);
$out = '$countries'." = array(\n";
foreach ($xml->country as $country)
{
$out .= "'{$country['code']}' => \"{$country['name']}\",\n";
}
$out .= ");";
file_put_contents('country_names.php', $out);
Alternately, you can save it as a CSV file and load it using PHP's fgetcsv() function. That would probably be preferable IMO. Or, heck, you could just save the XML and parse it when you load it.
I'm not sure how within Zend HTTp calls can be made, but here is probably a good resource to refer.
Use Yahoo!'s Geo data, which allows mapping of free form strings into WOE Ids. For countries, WOE Ids are the ISO 3166-1 codes.
To convert a free form string into a WOE Id, you can use the GeoPlanet APIs : http://developer.yahoo.com/geo/geoplanet/
You should have a look at Zend_Locale::getTranslation(). You may get a list (a simple array) of country names - and then you may use array_search() to get the needed "country-key"!
I have made an up-to-date collection of countrynames and ISO 3166 country codes over at:
https://github.com/johannesl/Internationalization
You can use it to convert both name => country code and reverse.
I'm also creating a collection of common country aliases that will appear on github.

Simplest way to detect client locale in PHP

I would like to be able to detect what country a visitor is from on my website, using PHP.
Please note that I'm not trying to use this as a security measure or for anything important, just changing the spelling of some words (Americans seems to believe that the word "enrolment" has 2 Ls.... crazy yanks), and perhaps to give a default option in a "Select your country" list.
As such, using a Geolocation database is a tad over-the-top and I really don't want to muck about with installing new PHP libraries just for this, so what's the easiest/simplest way to find what country a visitor is from?
PHP provides a function since 5.3.0 to parse the $_SERVER['HTTP_ACCEPT_LANGUAGE'] variable into a locale.
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
echo $locale; // returns "en_US"
Documentation: https://www.php.net/manual/en/locale.acceptfromhttp.php
Not guaranteed, but most browsers submit an Accept-Language HTTP header that specifies en-us if they're from the US. Some older browsers only said they are en, though. And not all machines are set up correctly to indicate which locale they prefer. But it's a good first guess.
English-UK based-users usually set their system or user locale to English-UK, which in default browser configurations should result in en-gb as the Accept Language header. (An earlier version of this said en-uk; that was a typo, sorry.) Other countries also have en locales, such as en-za (south africa), and, primarily theoretically, combinations like en-jp are also possible.
Geo-IP based guesses will less likely be correct on the preferred language/locale, however. Google thinks that content-negotiation based on IP address geolocation makes sense, which really annoys me when I'm in Japan or Korea...
You can check out the HTTP_ACCEPT_LANGUAGE header (from $_SERVER) that most browsers will send.
Take a look at Zend_Locale for an example, or maybe you might even want to use the lib.
You can do some IP comparaison without having a whole library to do it.
Solution #1
Use an API, this way nothing is needed from your side. This is a web API that let you know the country:
Example: http://api.hostip.info/get_html.php?ip=12.215.42.19
Return : Country: UNITED STATES (US)
Solution #2
But, Have you think to use the browser agent language? You might be able to know the type of english from it.
Solution #3
This website called BlockCountry let you have a list of IP by country. Of course, you do not want to block, but you can use the list of IP and compare them (get all US IP...) this might not be accurate...
Given your stated purpose, the Accept-Language header is a more suitable solution than IP-based geolocation. Indeed, it's precisely the intended purpose of Accept-Language.
I use the HTTP_ACCEPT_LANGUAGE
$localePreferences = explode(",",$_SERVER['HTTP_ACCEPT_LANGUAGE']);
if(is_array($localePreferences) && count($localePreferences) > 0) {
$browserLocale = $localePreferences[0];
$_SESSION['browser_locale'] = $browserLocale;
}
Parse $_SERVER["HTTP_ACCEPT_LANGUAGE"] to get country and browser's locale.
For identifying your visitors country I've used GeoIP extension, very simple to use.
The http://countries.nerd.dk service is what I use for IP-to-country mapping. It works really well and being based on DNS, is cached well too.
You can also download the database for local use if you don't want to rely on an external service.
Or you can do the following:
download 'geoip.dat' and geoip.inc from http://www.maxmind.com/app/geoip_country
in geoip.inc header you will find how to use it (eg. initialize and the rest...)
GeoIP extension is good choice.
One thing is which language viewer wants, second - which you can serve:
$SystemLocales = explode("\n", shell_exec('locale -a'));
$BrowserLocales = explode(",",str_replace("-","_",$_SERVER["HTTP_ACCEPT_LANGUAGE"])); // brosers use en-US, Linux uses en_US
for($i=0;$i<count($BrowserLocales);$i++) {
list($BrowserLocales[$i])=explode(";",$BrowserLocales[$i]); //trick for "en;q=0.8"
for($j=0;$j<count($SystemLocales);$j++) {
if ($BrowserLocales[$i]==substr($SystemLocales[$j],0,strlen($BrowserLocales[$i]))){
setlocale(LC_ALL, $SystemLocales[$j]);
break 2; // found and set, so no more check is needed
}
}
}
for example, mine system serves only:
C
POSIX
pl_PL.UTF-8
and my browser languages are: pl, en-US, en => so the only correct locale is pl_PL.UTF-8.
When no successful comparison is found - there's no setlocale at all.

Categories