PHPackages                             horde/nls - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. horde/nls

ActiveLibrary[Localization &amp; i18n](/categories/localization)

horde/nls
=========

Native language support library

v3.0.0(1w ago)14.2k↑57.9%48LGPL-2.1-onlyPHPPHP ^8.1

Since May 21Pushed 6d ago5 watchersCompare

[ Source](https://github.com/horde/Nls)[ Packagist](https://packagist.org/packages/horde/nls)[ Docs](https://www.horde.org/libraries/Horde_Nls)[ RSS](/packages/horde-nls/feed)WikiDiscussions FRAMEWORK\_6\_0 Synced yesterday

READMEChangelog (4)Dependencies (11)Versions (18)Used By (8)

Horde\\Nls Native Language Support
==================================

[](#hordenls-native-language-support)

A library for handling language data, country codes, timezones, TLD lookups and IP-to-country resolution.

Installation
------------

[](#installation)

```
composer require horde/nls
```

### Optional dependencies

[](#optional-dependencies)

```
# For reverse-DNS hostname lookups
composer require mikepultz/netdns2

# For MaxMind GeoIP2/GeoLite2 database lookups
composer require geoip2/geoip2
```

Usage
-----

[](#usage)

### Basic usage (injectable service)

[](#basic-usage-injectable-service)

```
use Horde\Nls\Nls;

$nls = new Nls();

// Country lookup
$nls->countries()->get('DE');          // 'Germany'
$nls->countries()->all();              // ['AD' => 'Andorra', 'AE' => 'United Arab Emirates', ...]
$nls->countries()->translated();       // Localized names, sorted by locale

// Language lookup
$nls->languages()->get('fr');          // 'French'

// Timezones
$nls->getTimezones();                  // ['Africa/Abidjan' => 'Africa/Abidjan', ...]

// Charset validation
$nls->checkCharset('UTF-8');           // true
$nls->checkCharset('NOT-REAL');        // false
```

### Data classes as arrays

[](#data-classes-as-arrays)

All data classes implement `IteratorAggregate`, `ArrayAccess`, and `Countable`:

```
$countries = new \Horde\Nls\Countries();

foreach ($countries as $code => $name) {
    echo "$code: $name\n";
}

echo $countries['US'];     // 'United States'
echo count($countries);    // 249
isset($countries['XX']);   // false
```

### Translation (explicit)

[](#translation-explicit)

Translation is never applied implicitly. Call `translated()` when you need localized output:

```
$countries = new \Horde\Nls\Countries();

$countries->all();         // English names (default)
$countries->translated();  // Localized via gettext, sorted by locale
```

### Country lookup from hostname/IP

[](#country-lookup-from-hostnameip)

```
use Horde\Nls\Nls;
use Horde\Nls\Dns\NativeResolver;
use Horde\Nls\Geoip\Geoip2Driver;

$nls = new Nls(
    resolver: new NativeResolver(),
    geoip: new Geoip2Driver('/path/to/GeoLite2-Country.mmdb'),
);

$result = $nls->getCountryByHost('example.de');
// ['code' => 'de', 'name' => 'Germany']

$result = $nls->getCountryByHost('8.8.8.8');
// ['code' => 'us', 'name' => 'United States'] (via GeoIP)
```

### Legacy code resolution

[](#legacy-code-resolution)

Retired ISO-3166 codes and old country names are handled by `LegacyCodes`:

```
$legacy = new \Horde\Nls\LegacyCodes();

$legacy->resolve('AN');                    // 'BQ' (Netherlands Antilles → Bonaire)
$legacy->resolve('YU');                    // 'RS' (Yugoslavia → Serbia)
$legacy->resolveName('Czech Republic');    // 'CZ'
$legacy->resolveName('Swaziland');         // 'SZ'
```

### GeoIP drivers

[](#geoip-drivers)

```
use Horde\Nls\Geoip\Geoip2Driver;
use Horde\Nls\Geoip\LegacyDatDriver;
use Horde\Nls\Geoip\NullDriver;

// MaxMind GeoIP2 (recommended)
$geoip = new Geoip2Driver('/path/to/GeoLite2-Country.mmdb');

// Legacy .dat format
$geoip = new LegacyDatDriver('/path/to/GeoIP.dat');

// No GeoIP (default)
$geoip = new NullDriver();
```

### DNS resolvers

[](#dns-resolvers)

```
use Horde\Nls\Dns\NullResolver;
use Horde\Nls\Dns\NativeResolver;
use Horde\Nls\Dns\NetDns2Resolver;

// No reverse DNS (default)
$resolver = new NullResolver();

// PHP built-in gethostbyaddr
$resolver = new NativeResolver();

// NetDNS2 library
$resolver = new NetDns2Resolver($netdns2Instance);
```

Architecture
------------

[](#architecture)

```
src/
├── Nls.php                          # Main injectable service
├── Translation.php                  # Horde\Translation integration
├── Countries.php                    # ISO-3166 country data
├── Languages.php                    # ISO-639-1 language data
├── Tld.php                          # TLD → country mapping
├── Alpha3.php                       # Alpha-2 → Alpha-3 codes
├── Carsigns.php                     # License plate prefixes
├── LegacyCodes.php                  # Retired code resolution
├── Coordinates/
│   ├── CoordinatesInterface.php     # Provider contract
│   └── StaticCoordinates.php        # Bundled city data
├── Dns/
│   ├── ResolverInterface.php        # Reverse DNS contract
│   ├── NullResolver.php
│   ├── NativeResolver.php
│   └── NetDns2Resolver.php
├── Geoip/
│   ├── GeoipInterface.php           # IP→country contract
│   ├── Geoip2Driver.php             # MaxMind GeoIP2/GeoLite2
│   ├── LegacyDatDriver.php          # MaxMind legacy .dat
│   └── NullDriver.php
└── DataRegeneration/
    └── IanaTldUpdater.php           # IANA TLD list updater

```

Upgrading from Horde\_Nls
-------------------------

[](#upgrading-from-horde_nls)

See [doc/UPGRADING.md](doc/UPGRADING.md) for a complete migration guide from the legacy `Horde_Nls` static API to the new injectable `Horde\Nls\Nls` service.

Requirements
------------

[](#requirements)

- PHP 8.1+
- ext-mbstring
- horde/translation ^3

License
-------

[](#license)

LGPL-2.1-only. See [LICENSE](LICENSE) for details.

###  Health Score

62

—

FairBetter than 99% of packages

Maintenance98

Actively maintained with recent releases

Popularity28

Limited adoption so far

Community36

Small or concentrated contributor base

Maturity80

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 78% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~340 days

Recently: every ~333 days

Total

14

Last Release

7d ago

Major Versions

2.2.1 → 3.0.0alpha22021-02-24

PHP version history (5 changes)2.0.4PHP &gt;=5.3.0,&lt;=6.0.0alpha1

2.1.1PHP &gt;=5.3.0,&lt;=8.0.0alpha1

3.0.0alpha2PHP ^7

v3.0.0alpha4PHP ^7.4 || ^8

v3.0.0RC1PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/c943a083635c28520599075eaea7ede2d743b7697b76e84d6bdc37e52cc8249b?d=identicon)[yunosh](/maintainers/yunosh)

![](https://www.gravatar.com/avatar/c931cd02664859360478593450d6c473a05bb12b209dfacfc534cd13257cc7ef?d=identicon)[ralflang](/maintainers/ralflang)

![](https://www.gravatar.com/avatar/e4f6c6771993db2ed500959b42353f6cf6a2ca0406d9617f7ae680f4504faa4a?d=identicon)[horde](/maintainers/horde)

![](https://www.gravatar.com/avatar/a7767adb66b45f2f05bcd44d49bc4e67efacd9ce05b161ce2d481d5dd6af025c?d=identicon)[mrubinsk](/maintainers/mrubinsk)

![](https://www.gravatar.com/avatar/816e2b926f25f8cd2939054c7a7173011b4303d690e25ab61bf33cf8c7cf71ae?d=identicon)[tdannhauer](/maintainers/tdannhauer)

---

Top Contributors

[![yunosh](https://avatars.githubusercontent.com/u/379318?v=4)](https://github.com/yunosh "yunosh (191 commits)")[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (24 commits)")[![slusarz](https://avatars.githubusercontent.com/u/381003?v=4)](https://github.com/slusarz "slusarz (15 commits)")[![mrubinsk](https://avatars.githubusercontent.com/u/66822?v=4)](https://github.com/mrubinsk "mrubinsk (8 commits)")[![wrobel](https://avatars.githubusercontent.com/u/10232?v=4)](https://github.com/wrobel "wrobel (2 commits)")[![renan](https://avatars.githubusercontent.com/u/28046?v=4)](https://github.com/renan "renan (2 commits)")[![sathieu](https://avatars.githubusercontent.com/u/741106?v=4)](https://github.com/sathieu "sathieu (1 commits)")[![kklem0](https://avatars.githubusercontent.com/u/3030930?v=4)](https://github.com/kklem0 "kklem0 (1 commits)")[![TDannhauer](https://avatars.githubusercontent.com/u/6716033?v=4)](https://github.com/TDannhauer "TDannhauer (1 commits)")

---

Tags

languagecountrytld

### Embed Badge

![Health badge](/badges/horde-nls/health.svg)

```
[![Health](https://phpackages.com/badges/horde-nls/health.svg)](https://phpackages.com/packages/horde-nls)
```

###  Alternatives

[codezero/laravel-localized-routes

A convenient way to set up, manage and use localized routes in a Laravel app.

544664.5k4](/packages/codezero-laravel-localized-routes)[horde/imap_client

IMAP client library

275.5k18](/packages/horde-imap-client)[codezero/laravel-localizer

Automatically detect and set an app locale that matches your visitor's preference.

50404.9k4](/packages/codezero-laravel-localizer)[codezero/browser-locale

Get the most preferred locales from your visitor's browser.

162.1M18](/packages/codezero-browser-locale)[opgginc/codezero-laravel-localized-routes

A convenient way to set up, manage and use localized routes in a Laravel app.

29119.1k1](/packages/opgginc-codezero-laravel-localized-routes)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
