Giter Club home page Giter Club logo

php-isocodes's Introduction

Stand With Ukraine 🇺🇦

SWUbanner


PHP ISO Codes

Continuous integration Latest Stable Version Coverage Status Total Downloads Daily Downloads

⭐ This library used to get localized names of countries, currencies, languages and scripts.

📦 Based on Python's pycountry and Debian's iso-codes.

👅 Current translation status: https://salsa.debian.org/iso-codes-team/iso-codes#status-of-translations

Table of contents

ISO Standards

  • ISO 3166-1: Country codes (alpha-2, alpha-3, numeric)
  • ISO 3166-2: Principal subdivisions (e.g., provinces or states) of all countries coded in ISO 3166-1
  • ISO 3166-3: Historic countries (alpha-2, alpha-3, alpha-4, numeric)
  • ISO 15924: Scripts
  • ISO 4217: Currencies
  • ISO 639-3: Languages

Installation

You may use this library in different modes:

  • sokil/php-isocodes (this library) - install library without database and messages and setup periodic updates of database and messages by yourself with cron or inside CI/CD pipeline with ./bin/update_iso_codes_db.sh
  • sokil/php-isocodes-db-only - if you do not need internationalisation, use this library. Database already inside. To update database just periodically update this library.
  • sokil/php-isocodes-db-i18n - if you need internationalisation, use this library. Database and messages already inside. To update database just periodically update this library.

💾 Library with included database and localization

To install library with database and i18n:

Latest Stable Version Total Downloads Daily Downloads

composer require sokil/php-isocodes-db-i18n

💾 Library with included database and without localization

You may also install library with only database (no i18n will be available):

Latest Stable Version Total Downloads Daily Downloads

composer require sokil/php-isocodes-db-only

💾 Library without database and localization, requires manual database installation and updates

You can install library through Composer:

composer require sokil/php-isocodes

Database and gettext files located in related packages inside databases and messages directories. This packages periodically updated with package version increment.

If you want to update database, use script ./bin/update_iso_codes_db.sh. Call this script by cron, during deploy process or when build your docker image.

./bin/update_iso_codes_db.sh {mode} {base_dir} {build_dir}
Argument Required Description
mode Required May be "all" or "db_only". In "all" mode update database (json files) and locallisation (po and mo files), in "db_only" only database will update
base_dir Required Dir where to place database and messages
build_dir Optional. Default: "/tmp/iso-codes-build" Dir where source directory cloned and files original files processed.

Now you need to configure factory to use this directory:

<?php

$databaseBaseDir = '/var/isocodes';

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory($databaseBaseDir);

Translation drivers

Translation drivers required when need to get local names of iso entities.

Translation driver must implement Sokil\IsoCodes\TranslationDriver\TranslationDriverInterface.

Instance of driver may be passed to IsoCodesFactory. If it not passed, default GettextExtensionDriver will be used.

<?php

// gettext driver
$isoCodes = new IsoCodesFactory();
$isoCodes = new IsoCodesFactory(null, new GettextExtensionDriver());

// symfony driver
$driver = new SymfonyTranslationDriver();
$driver->setLocale('uk_UA');

$isoCodes = new IsoCodesFactory(
    null,
    $driver
);

// dummy driver
$isoCodes = new IsoCodesFactory(
    null,
    new DummyDriver()
);

Gettext extension driver

This is default translation driver. It requires ext-gettext.

<?php

// gettext driver
$isoCodes = new IsoCodesFactory();
$isoCodes = new IsoCodesFactory(null, new GettextExtensionDriver());

Locale configuration

Before using IsoCodes database you need to setup valid locale to get translations worked, because ext-gettext uses system local, configured by setlocale.

<?php

// define locale
putenv('LANGUAGE=uk_UA.UTF-8');
putenv('LC_ALL=uk_UA.UTF-8');
setlocale(LC_ALL, 'uk_UA.UTF-8');

// init database
$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();

// get languages database
$languages = $isoCodes->getLanguages();

// get local name of language
echo $languages->getByAlpha2('uk')->getLocalName(); // will print 'українська'

To get list of available locales, execute under console:

$ locale -a
uk_UA
uk_UA.koi8u
uk_UA.utf8

If you don't see required locales in list, you may install them manually (for Ubuntu):

$ locale-gen uk_UA.utf8
Generating locales...
  uk_UA.utf-8... done
Generation complete.

Symfony Translation driver

<?php

$driver = new SymfonyTranslationDriver();
$driver->setLocale('uk_UA');

$isoCodes = new IsoCodesFactory(
    null,
    $driver
);

Dummy driver

This driver may be used, when localisation of names does not require, and only database of codes is required.

<?php

$isoCodes = new IsoCodesFactory(
    null,
    new DummyDriver()
);

Usage

Factory

All databases may be created through factory:

<?php
$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$languages = $isoCodes->getLanguages();

There are large databases: subdivisions and languages. Loading of entire database into memory may require lot of RAM and time to create all entries in memory.

So there are scenarios of usage: with optimisations of memory and with optimisation of time.

Memory optimisation

Database splits into partition files.

Fetching some entry will load only little part of database. Loaded entries not stored statically.

This scenario may be useful when just few entries need to be loaded, for example on web request when one entry fetched.

This may require a lot of file read operations.

Input-output optimisations

Entire database loaded into memory from single JSON file once.

All entries created and stored into RAM. Next read of save entry will just return it without io operations with files and building objects.

This scenario may be useful for daemons to decrease file operations, or when most entries will be fetched from database.

This may require a lot of RAM for storing all entries.

Countries database (ISO 3166-1)

Country contains next names:

Name Description Example
Name Required Moldova, Republic of
Official Name Optional Republic of Moldova
Common Name Optional Moldova
Localised Name Optional Молдова

This names may be get from country entity:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$country = $isoCodes->getCountries()->getByAlpha2('UA');
echo $country->getName();
echo $country->getLocalName();
echo $country->getOfficialName();
echo $country->getCommonName();

Also you may get flag of country:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$country = $isoCodes->getCountries()->getByAlpha2('UA');
echo $country->getFlag();

Get localized name of country by it's alpha2 code:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$isoCodes->getCountries()->getByAlpha2('UA')->getLocalName();

Get localized name of country by it's alpha2 code:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$isoCodes->getCountries()->getByAlpha2('UKR')->getLocalName();

Get localized name of country by it's numeric code:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$isoCodes->getCountries()->getByAlpha2('804')->getLocalName();

Get localised list of countries

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
foreach($isoCodes->getCountries() as $country) {
  echo $country->getLocalName();
}

Subdivisions database (ISO 3166-2)

<?php

$isoCodes = new IsoCodesFactory();

$subDivisions = $isoCodes->getSubdivisions();

// get subdivision by code
$subDivision = $subDivisions->getByCode('UA-43');

// get subdivision code
$subDivision->getCode(); // UA-43

// get subdivision name
$subDivision->getName(); // Respublika Krym

// get localised subdivision name
$subDivision->getLocalName(); // Автономна Республіка Крим

// get subdivision type
$subDivision->getType(); // 'Autonomous republic'

Historic countries database (ISO 3166-3)

<?php

$isoCodes = new IsoCodesFactory();

$countries = $isoCodes->getHistoricCountries();

$country = $countries->getByAlpha4('ZRCD');

$country->getName(); //'Zaire, Republic of'
$country->getAlpha4(); // 'ZRCD'
$country->getAlpha3(); // 'ZAR'
$country->getAlpha2(); // 'ZR'
$country->getWithdrawalDate(); // '1997-07-14'
$country->getNumericCode(); // 180

Scripts database (ISO 15924)

<?php
$isoCodes = new IsoCodesFactory();

$scripts = $isoCodes->getScripts();

$script = $scripts->getByAlpha4('Aghb');

$script->getName(); // Caucasian Albanian
$script->getLocalName(); // кавказька албанська
$script->getAlpha4(); // Aghb
$script->getNumericCode(); 239

Currencies database (ISO 4217)

<?php

$isoCodes = new IsoCodesFactory();

$currencies = $isoCodes->getCurrencies();

$currency = $currencies->getByLetterCode('CZK');

$currency->getName(); // Czech Koruna
$currency->getLocalName(); // Чеська крона
$currency->getLetterCode(); // CZK
$currency->getNumericCode(); // 203

Languages database (ISO 639-3)

<?php
$isoCodes = new IsoCodesFactory();

$languages = $isoCodes->getLanguages();

$language = $languages->getByAlpha2('uk');

$language->getAlpha2(); // uk

$language->getName(); // Ukrainian

$language->getLocalName(); // українська

$language->getAlpha3(); // ukr

// Scope of denotation, see mote at https://iso639-3.sil.org/about/scope
$language->getScope(); // I

// Type of language, see https://iso639-3.sil.org/about/types
$language->getType(); // L

$language->getInvertedName(); // null

Tests

To start docker tests run following command:

./tests/docker/run-test.sh [PHP_VERSION]

For example for PHP 7.1 run following command:

./tests/docker/run-test.sh 7.1

See also

php-isocodes's People

Contributors

henriquemoody avatar ipgpay-pm avatar madeorsk avatar peter279k avatar shengslogar avatar sokil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

php-isocodes's Issues

PHP 8.1.1 - PHP Deprecated Warning: AbstractDatabase::current() ReturnTypeWillChange

$ php composer.phar info | grep iso
sokil/php-isocodes 4.0.1 ISO country, subdivision, language, currency and scri...
sokil/php-isocodes-db-i18n 4.0.1 Database and internationalisation filed for ISO count...

$ php -v
PHP 8.1.1 (cli) (built: Dec 17 2021 23:49:52) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies


When running one of my scripts I'm getting the deprecation message below when executing the following command:

$country = ((new IsoCodesFactory())->getCountries()->getByAlpha2($countryCode));

PHP Deprecated: Return type of Sokil\IsoCodes\AbstractDatabase::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in ***/vendor/sokil/php-isocodes/src/AbstractDatabase.php on line 182

Splitting up ISO 3166 2 per country

First of all, thank you very much for maintaining this library, very much appreciated! I am very interested to incorporate this library into a library that I have been maintaining in a while called Respect\Validation because I don't want to deal with keeping this type of data in sync.

I noticed that you load all the subdivisions (ISO 3166 2) at once and then you iterate on them to fetch them by Country. Wouldn't it be optimal to have once file per country instead?

I get that this is the implementation of iso-codes, but they don't have to worry with web environment as most of PHP code has to deal with.

Undefined constant "Sokil\IsoCodes\TranslationDriver\LC_MESSAGES"

I am using a windows development machine with

PHP 8.0.2 (cli) (built: Feb 3 2021 18:36:40) ( ZTS Visual C++ 2019 x64 )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans

and I am getting

Undefined constant "Sokil\IsoCodes\TranslationDriver\LC_MESSAGES" in \vendor\sokil\php-isocodes\src\TranslationDriver\GettextExtensionDriver.php:37

It seems that my installation does not have the LC_MESSAGES defined. Trying to find some solution for this I came across this post.

I tried something like this and it seems it work for my installation.

Cant Use en locale

Hello im using your library, but i can't use en or en_US or en_GB languages, it giving, but it working with another localizations

   InvalidArgumentException 

  Directory does not contain valid resource

  at ****\vendor\sokil\php-isocodes\src\TranslationDriver\SymfonyTranslationDriver.php:46
     42▕             }
     43▕         }
     44▕
     45▕         if ($validPathToMoFile === null) {
  ➜  46▕             throw new \InvalidArgumentException('Directory does not contain valid resource');
     47▕         }
     48▕
     49▕         $this->translator->addResource(
     50▕             'mo',
Sokil\IsoCodes\TranslationDriver\SymfonyTranslationDriver::configureDirectory("3166-1", "****\vendor\sokil\php-isocodes\src/../../php-isocodes-db-i18n/messages")

My code:

$driver = new Sokil\IsoCodes\TranslationDriver\SymfonyTranslationDriver();
$driver->setLocale('en');
$__iso_codes = new \Sokil\IsoCodes\IsoCodesFactory(null, $driver);
$__iso_codes->getCountries()->getByAlpha2('UA');
		``

Use of mutation testing in php-isocodes - Help needed

Hello there!

My name is Ana. I noted that you use the mutation testing tool infection in the project.
I am a postdoctoral researcher at the University of Seville (Spain), and my colleagues and I are studying how mutation testing tools are used in practice. With this aim in mind, we have analysed over 3,500 public GitHub repositories using mutation testing tools, including yours! This work has recently been published in a journal paper available at https://link.springer.com/content/pdf/10.1007/s10664-022-10177-8.pdf.

To complete this study, we are asking for your help to understand better how mutation testing is used in practice, please! We would be extremely grateful if you could contribute to this study by answering a brief survey of 21 simple questions (no more than 6 minutes). This is the link to the questionnaire https://forms.gle/FvXNrimWAsJYC1zB9.

Drop me an e-mail if you have any questions or comments ([email protected]). Thank you very much in advance!!

Attempted to call function "bindtextdomain" from the global namespace.

Hi.
I've Installed and maintained this package (on Symfony6, php 8.1, docker/ubuntu)
and I got an error "Attempted to call function "bindtextdomain" from the global namespace."

I try it locally from docker container.
`
class IsoCodesService
{
public function __construct()
{
// define locale
putenv('LANGUAGE=uk_UA.UTF-8');
putenv('LC_ALL=uk_UA.UTF-8');
setlocale(LC_ALL, 'uk_UA.UTF-8');
$this->isoCodes = new IsoCodesFactory(null, new GettextExtensionDriver());
}

public function getAlpha3ByAlpha2(string $lang = 'en'): string
{
    $languages = $this->isoCodes->getLanguages();
    $language = $languages->getByAlpha2($lang);
    return $language->getAlpha3();
}

}`

Чи не могли б ви допомогти, будьлазка?

How can I get the common name in countries ?

Some country names return incorrectly. For instance: Tanzania, United Republic of | Moldova, Republic of.
In iso_3166-1.json database return:

{
"alpha_2": "MD",
"alpha_3": "MDA",
"common_name": "Moldova",
"flag": "🇲🇩",
"name": "Moldova, Republic of",
"numeric": "498",
"official_name": "Republic of Moldova"
},

How can I get the common_name ?

Subdivisions->getAllByCountryCode($code) throws exceptions if no subdivisions are present

Just wondering if you would consider returning a null set of subdivisions for a country code if no subdivisions exist rather than throwing an internal exception due to the missing country_code key?

public function getAllByCountryCode($code) { try { $subdivisions = $this->find('country_code', $code); } catch (\Exception $e) { // do nothing $subdivisions = null; } return $subdivisions; }

Reduce the size of the repository

First of all, thank you for all of the work you put into this library, it's very useful and I'm very happy with it.

I recently integrated this library into Respect/Validation:

The problem, however, is that it increased the size of the repository way too much: Respect/Validation#1340

If I look at the directory size in this repository, I get this:

$ du -sh *
4.0K	CHANGELOG.md
4.0K	CONTRIBUTING.md
4.0K	LICENSE
12K	README.md
12K	benchmarks
16K	bin
4.0K	composer.json
4.7M	databases
4.0K	infection.json.dist
86M	messages
4.0K	phpbench.json
4.0K	phpcs.xml.dist
4.0K	phpunit.xml.dist
4.0K	psalm.xml
104K	src
44K	tests

Clearly, the messages directory is the cause of the issues users are experiencing. The funny is that, for listing the data in English (which is what I use in the validation), none of those translations are useful.

Would be an idea to have those messages as a third-party repository that could be just a suggestion, so that people can chose whether they want to have all the translations or not?

Allow configure external datasource for database update not linked to package

Extract AbstractDatabase::DATABASE_PATH and AbstractDatabase::MESSAGES_PATH from constants to factory.

This will allow configure external data source and update database without updating library.

Allso required to add parameter targetDir to update_db.sh to specify place where database will be stored. This skrimp then may be add to cron.

Class "Sokil\IsoCodes\IsoCodesFactory" not found

Got this error in my XAMPP dev environment after running:

composer require --dev sokil/php-isocodes-db-only

And calling the library with the following code from the docs:

$isoCodes = new \Sokil\IsoCodes\IsoCodesFactory();
$country = $isoCodes->getCountries()->getByAlpha2('UA');

Any idea why this is?

Drop PHP 5 support

Is there a specific reason why you're keeping the support with version 5.5 of PHP since PHP itself does not support that anymore?

Maybe you could modernize the codeback in master and still keep the support for old versions in another branch.

Help on Windows

Hi,

My PHP website is hosted on Windows Server, using countries and currencies based on php-isocodes; but, when switching between languages, countries and currencies remains the same locale!
Please help with that!

Thanks!

Expose the file loader

Hi! Thanks for the library, it has been pretty useful.

I just have one question... Would it be possible to "expose" the json file loader? I'd like to overwrite it and return my custom object.

Use case: I wrote a translation driver to make better use of the opcache, but I can't do the same for the json files.


Other issues that I had:

  1. The default translation driver doesn't work for me: I tried to load data from different locales, but it was just returning data in en_US (I didn't inspect much as I can't use the gettext extension anyway).
  2. SymfonyTranslationDriver: as I consume different data, it keeps growing in memory, it would be nice to have a setting to discard it.
  3. SymfonyTranslationDriver: when I try to load inexistent translations, it throws an InvalidArgumentException (so I had to fallback to the DummyDriver), that's ok! But the default driver doesn't throw, so it would be good to have the same behavior and maybe a setting to retrieve a default value (en_US).

Missing or uncommon common names

Hi Sokil, firstly thanks for this library and the great work you've done and continue to do on it.

I was testing the library and noticed that many of the countries have missing common names or their common name is (in English) not commonly used. I'd prefer to make these changes upstream instead of just our own application, so I wanted to ask permission here so I can go ahead and make this commit. The proposed changes that I would make are:

Bonaire, Sint Eustatius and Saba = Carribbean Netherlands
British Indian Ocean Territory = the British Indian Ocean Territory
Central African Republic = the Central African Republic
Congo, the Democratic Republic of the = the DRC
Congo = Congo-Brazzaville
Côte d'Ivoire = the Ivory Coast
Falkland Islands (Malvinas) = the Falkland Islands
Faroe Islands = the Faroe Islands
French Southern Territories = the French Southern Territories
Holy See (Vatican City State) = Vatican City
Isle of Man = the Isle of Man
Marshall Islands  = the Marshall Islands
Micronesia, Federated State of = the Federated States of Micronesia
Northern Mariana Islands = the Northern Mariana Islands
Palestine, State of = Palestine
Russian Federation = Russia
Philippines = the Philippines
Pitcairns = the Pitcairn Islands
Saint Martin (French Part) = Saint Martin
Sint Maarten (Dutch Part) = Sint Maarten
Solomon Islands = the Solomon Islands
Turks and Caicos Islands = the Turks and Caicos Islands
United Arab Emirates = the United Arab Emirates
United Kingdom = the United Kingdom
United States = the United States
Virgin Islands, British = the British Virgin Islands
Vrigin Islands, U.S. = the U.S. Virgin Islands

Some of these are taken from sources like Wikipedia titles, some from my own knowledge/experience of how these countries would be used by an English speaker, especially in the context of being used in an interface, and some just have the definite article added to nouns like islands because it sounds much more natural in English sentences and avoids having to programmatically check for and add it one at a time.

Let me know what you think.

Dynamic translations

Hello,
thanks for this great package.
I was wondering: in our application, we have user language in ISO639 format (en, es, fr, de, it....)
How would be possible to return translations of countries and languages according to this? I saw you allow to set LC_ALL variable and so on but I was wondering which might be the possibilities to avoid that.

Thanks!

Some country names are incorrect

Some country names are incorrect, for example "Congo, The Democratic Republic of the". These names end with "Republic of", "Republic of the", "States of", "State of" , so consist of 2 part , seperates with comma.

Language Tag

https://tools.ietf.org/html/rfc5646.html

langtag       = language
                 ["-" script]

 language      = 2*3ALPHA            ; shortest ISO 639 code
                 ["-" extlang]       ; sometimes followed by
                                     ; extended language subtags
               / 4ALPHA              ; or reserved for future use
               / 5*8ALPHA            ; or registered language subtag

 script        = 4ALPHA              ; ISO 15924 code

pt-BR - português do Brasil

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.