A lightweight, high-performance key-value format parser and serializer for PHP.
Designed for translation files β but works great for any structured text data.
Atlin is a plain-text key-value format with minimal syntax and maximum readability.
| Rule | Behaviour |
|---|---|
@key at line start |
Declares a key. Everything after @ on that line is the key name. |
Line(s) after key (not starting with @) |
The value for that key. Multi-line values are supported. |
Exactly one blank line before a @ line |
Ignored β used as a visual separator between entries. |
More than one blank line before a @ line |
All except the last are part of the value. |
| Blank line(s) at end of file | Always ignored (treated as file-ending whitespace). |
| Text before any key | Assigned to the empty-string key "". |
@ alone on a line |
Produces the empty-string key "". |
| Duplicate keys | Values are concatenated with a newline (\n). |
\@ at line start |
Escaped β treated as a literal @ in the value. |
\# at line start |
Escaped β treated as a literal # in the value (when comments enabled). |
@ not at line start |
Always part of the value (e.g. email addresses). |
@ with a leading space (e.g. @foo) |
Part of the value, NOT a key. |
The blank line rule is precise:
@key
value
@next
β Single blank line = separator β key = "value" β
@key
value
@next
β Two blank lines = first is value content, second is separator β key = "value\n" β
@key
value
@next
β Three blank lines = first two are value content, last is separator β key = "value\n\n" β
@key
value
β Trailing blank line at EOF = ignored β key = "value" β
@app.name
My Awesome App
@app.description
This is a multi-line
description of the app.
@button.save
Save
@button.cancel
Cancel
@email.signature
Best regards,
The Team
\@this is not a key, it is a value without a preceding key declaration
@note
Send feedback to support@example.com
Parsed result:
[
'app.name' => 'My Awesome App',
'app.description' => "This is a multi-line\ndescription of the app.",
'button.save' => 'Save',
'button.cancel' => 'Cancel',
'email.signature' => "Best regards,\nThe Team",
'' => '@this is not a key, it is a value without a preceding key declaration',
'note' => 'Send feedback to support@example.com',
]@terms
By using this app you agree to our terms.
@terms
Updated: January 2026.
Result:
[
'terms' => "By using this app you agree to our terms.\nUpdated: January 2026.",
]- Human-readable β no quotes, no special delimiters, no indentation rules.
- Multi-line values β just keep writing on the next lines.
- Precise blank line control β one blank = separator, more = content.
- Zero noise β trailing blank lines at EOF are always ignored.
- Unicode-safe β key names can be any Unicode string (Persian, Arabic, CJK, etc.).
- Fast β single O(n) pass parser with zero regex.
composer require nabeghe/atlinRequires PHP β₯ 7.4.
use Nabeghe\Atlin\Atlin;
$atlin = new Atlin();
// Parse a string
$data = $atlin->parse("@hello\nHello, World!");
echo $data['hello']; // Hello, World!
// Parse a file
$data = $atlin->parseFile(__DIR__ . '/lang/en.atlin');
// Serialize an array back to Atlin format
$text = $atlin->serialize([
'greeting' => 'Hi!',
'farewell' => 'Bye!',
]);Atlin supports three cache backends. Caching is disabled by default β enable
it by passing an AtlinConfig with a cache driver.
Stores the parsed PHP array as a plain <?php return [...]; file, which benefits
from OPcache for extremely fast cold reads β no deserialization needed.
use Nabeghe\Atlin\Atlin;
use Nabeghe\Atlin\Cache\FileCache;
use Nabeghe\Atlin\Config\AtlinConfig;
$cache = new FileCache('/path/to/cache/dir');
$config = new AtlinConfig(
cache: $cache,
cacheTtl: 0, // 0 = store indefinitely
contentHashKey: true // auto-invalidate when source content changes
);
$atlin = new Atlin($config);
// The file path is used as the cache key automatically
$data = $atlin->parseFile('/path/to/lang/en.atlin');use Nabeghe\Atlin\Cache\ApcuCache;
$cache = new ApcuCache('myapp:'); // optional key prefix
$config = new AtlinConfig($cache, 3600); // TTL: 1 hour
$atlin = new Atlin($config);use Nabeghe\Atlin\Cache\RedisCache;
// phpredis extension
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$cache = new RedisCache($redis, 'myapp:');
$config = new AtlinConfig($cache, 3600);
$atlin = new Atlin($config);Works with both the phpredis extension and Predis client.
// Invalidate a single entry
$atlin->invalidate('/path/to/lang/en.atlin');
// Flush all entries managed by the current driver
$atlin->flushCache();
// Check if the driver is available
$atlin->getCache()->isAvailable(); // bool| Driver | Speed | Persistence | Multi-server | Requirements |
|---|---|---|---|---|
NullCache |
β | β | β | none (default) |
FileCache |
β‘β‘ (+ OPcache) | β | β | writable directory |
ApcuCache |
β‘β‘β‘ | β | β | ext-apcu |
RedisCache |
β‘β‘ | β | β | ext-redis or Predis |
Parse an Atlin-formatted string into an associative array.
Optionally provide a $cacheKey to enable caching for this content.
Read and parse an Atlin file.
Uses the file path as the cache key when $useCache is true.
Convert an associative array back to Atlin format.
Set $blankLines to false to omit blank separators between entries.
Manually invalidate a cache entry by its logical key.
Remove all cache entries managed by the current driver.
Access the underlying cache driver instance.
nabeghe/atlin/
βββ src/
β βββ Atlin.php β Main parser/serializer class
β βββ Cache/
β β βββ CacheInterface.php β Contract for all cache drivers
β β βββ NullCache.php β No-op driver (caching disabled)
β β βββ ApcuCache.php β APCu in-memory driver
β β βββ RedisCache.php β Redis driver (phpredis / Predis)
β β βββ FileCache.php β PHP opcode file driver
β βββ Config/
β β βββ AtlinConfig.php β Immutable configuration value-object
β βββ Exception/
β βββ AtlinException.php β Base library exception
β βββ CacheException.php β Cache operation exception
βββ tests/
β βββ AtlinTest.php β Full parser/serializer test suite
β βββ Cache/
β βββ FileCacheTest.php β FileCache unit tests
β βββ ApcuCacheTest.php β ApcuCache unit tests (auto-skipped if unavailable)
βββ composer.json
βββ phpunit.xml
βββ README.md
# Install dependencies
composer install
# Run all tests
composer test
# Run with coverage report (requires Xdebug or PCOV)
composer test-coveragePHPUnit 10 or 11 is supported.
APCu tests are automatically skipped when the extension is not loaded.
To enable APCu in CLI (for local testing), add to your php.ini:
apc.enable_cli=1Licensed under the MIT license, see LICENSE.md for details.