Skip to content

FileTranslation ​

File: src/Services/FileTranslation.phpNamespace: Unusualify\Modularous\ServicesExtends: JoeDixon\Translation\Drivers\File

Concrete file-based translation driver used by Modularous. Adds cross-path sync on top of the upstream File driver — comparing translation files in two different directories and copying missing keys from one to the other. Powers the modularous:sync:translations Artisan command, which pushes the package's bundled language files into the host application's lang/ directory.

Its transitive parent, Translation, supplies scanning and source-locale merge utilities; this class focuses on file I/O and diff.

Class Signature ​

php
class FileTranslation extends File
{
    public $disk;
    public $languageFilesPath;
    public $sourceLanguage;
    public $scanner;

    public function __construct(Filesystem $disk, $languageFilesPath, $sourceLanguage, $scanner);
}

The constructor re-exposes the parent's four dependencies as public properties so the instance can spawn temporary clones pointing at different $languageFilesPath values (used throughout the cross-path helpers).

Language Listing ​

MethodSignatureReturns
getLanguagesExcept(array $languages): arrayAll available languages minus the given list
getLanguagesOnly(array $languages): arrayIntersection of available languages and the given list

Both wrap parent::allLanguages() with array_diff / array_intersect.

Cross-Path Helpers ​

All of the following spawn ephemeral FileTranslation instances bound to arbitrary paths — this is the pattern that makes package ↔ app file sync possible without reconfiguring the Laravel service container.

getTranslationsFromPath($languageFilesPath, $language): Collection ​

php
$tempInstance = new static($this->disk, $languageFilesPath, $this->sourceLanguage, $this->scanner);
return $tempInstance->allTranslationsFor($language);

Loads all translations from an arbitrary path for one language. No global state is mutated — the temporary instance is discarded after the call.

findMissingKeysFromPath($sourcePath, $targetPath, $language): array ​

Diffs two paths for a single language. Delegates to compareTranslations() internally and returns a [type => [group => [key => value]]] tree containing only keys present in $sourcePath but missing from $targetPath.

findAllMissingKeys($sourcePath, $targetPath): array ​

Iterates every language present in $sourcePath (via a throwaway FileTranslation rooted there) and returns:

php
[
    'en' => [ /* missing tree for en */ ],
    'tr' => [ /* missing tree for tr */ ],
    // ... languages with no missing keys are omitted
]

syncMissingKeysToPath($sourcePath, $targetPath, $language, $missingKeys): void ​

Writes the provided missing-keys tree into $targetPath. Branches by type:

  • type === 'single' → syncSingleTranslations() (JSON)
  • otherwise → syncGroupTranslations() (PHP file)

syncAllMissingKeys($sourcePath, $targetPath): array ​

End-to-end sync for every language. Returns a stats array:

php
[
    'languages' => [
        'en' => 12,   // 12 keys synced for English
        'tr' => 5,    // 5 keys synced for Turkish
    ],
    'total_keys' => 17,
]

This is the method called by modularous:sync:translations.

Internal Sync Helpers ​

Protected methods invoked by syncMissingKeysToPath():

MethodRole
compareTranslations(Collection $source, Collection $target): arrayNested loop that builds the missing-keys tree — $target->get($type)->get($group)->has($key) misses become entries in $missing
syncGroupTranslations($targetInstance, $language, $group, $translations)Loads existing target group translations, merges the new values, and calls saveGroupTranslations()
syncSingleTranslations($targetInstance, $language, $group, $translations)Same flow for single (JSON) translations, writing via saveSingleTranslationsToPath()
saveSingleTranslationsToPath($targetInstance, $language, $group, Collection $translations)Writes JSON to {languageFilesPath}/vendor/{namespace}/{locale}.json when the group is namespaced ({namespace}::single), else {languageFilesPath}/{locale}.json. Creates the directory (0755) when missing and uses JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT

Save Paths ​

saveGroupTranslations($language, $group, $translations): void ​

Persists a group translation file. Normalises input (Collection → array), sorts keys alphabetically (ksort), and expands dot-notation keys back into a nested array via array_undot().

Two write paths:

Group formatOutput path
Plain (messages){languageFilesPath}/{locale}/{group}.php
Namespaced (admin::users){languageFilesPath}/vendor/{namespace}/{locale}/{group}.php (via saveNamespacedGroupTranslations)

Both branches use php_array_file_content($translations) to render the PHP array.

saveNamespacedGroupTranslations($language, $group, $translations): void (private) ​

Splits the namespaced group on ::, ensures the vendor language directory exists, and writes the translation array to the resolved path with php_array_file_content().

Translation File Layout ​

TypeStorageFormat
Grouplang/{locale}/{group}.phpPHP array
JSON (single)lang/{locale}.jsonJSON object
Namespaced grouplang/vendor/{namespace}/{locale}/{group}.phpPHP array
Namespaced JSONlang/vendor/{namespace}/{locale}.jsonJSON object (written by saveSingleTranslationsToPath() when the group is {namespace}::single)
  • Translation — abstract base class (scanning, source-locale merge, add())
  • modularous:sync:translations — command that drives syncAllMissingKeys()
  • FileLoader — multi-path translation loader that reads files written by this driver