19declare(strict_types=1);
72 if (defined(
'CLIENT_DATA_DIR')) {
76 $ilias_absolute_path ??= dirname(__DIR__, 5);
77 $ini_file = rtrim($ilias_absolute_path,
'/') .
'/ilias.ini.php';
78 if (!is_file($ini_file) || !is_readable($ini_file)) {
81 $ini = @parse_ini_file($ini_file,
true);
82 if (!is_array(
$ini)) {
114 return is_dir($client_data_dir) ? $client_data_dir :
null;
124 string $ilias_absolute_path,
131 . sprintf(self::shippedFileNamePattern($directory), $lang_key);
143 $pattern = self::shippedFileNamePattern($directory);
144 $base = self::shippedDirectoryPath($ilias_absolute_path, $directory);
145 [$before, $after] = explode(
'%s',
$pattern, 2);
146 $name_format =
'/\A' . preg_quote($before,
'/') .
'([a-z]{2})' . preg_quote($after,
'/') .
'\.po\z/';
149 foreach (glob($base . sprintf(
$pattern,
'*') .
'.po') ?: [] as $file) {
150 if (is_file($file) && preg_match($name_format, basename($file), $matches) === 1) {
151 $files[$matches[1]] = $file;
154 ksort(
$files, SORT_STRING);
166 return self::shippedDirectoryPath($ilias_absolute_path, $directory)
167 . self::templateFileName(self::shippedFileNamePattern($directory), $directory->
getPrefix());
178 foreach (glob(rtrim($ilias_absolute_path,
'/') .
'/' . self::SHIPPED_TEMPLATES) ?: [] as $file) {
179 $module = basename($file,
'.pot');
180 if (self::isValidModule(
$module) && is_file($file)) {
181 $templates[
$module] ??= dirname($file);
195 $template = self::shippedTemplatePath($ilias_absolute_path, $directory);
197 return basename($template) === $directory->
getPrefix() .
'.pot'
198 && fnmatch(rtrim($ilias_absolute_path,
'/') .
'/' . self::SHIPPED_TEMPLATES, $template, FNM_PATHNAME)
199 && is_file($template);
209 $name = trim(str_replace(
'%s',
'',
$pattern),
'_-.');
211 return ($name ===
'' ?
$module : $name) .
'.pot';
216 return rtrim($ilias_absolute_path,
'/') .
'/' . ltrim($directory->
getPath(),
'/');
229 ? $directory->getShippedFileNamePattern()
231 self::assertValidShippedFileNamePattern(
$pattern);
245 || preg_match(
'/\A[A-Za-z0-9_.\-]*%s[A-Za-z0-9_.\-]*\z/',
$pattern) !== 1
247 throw new \InvalidArgumentException(sprintf(
'"%s" is not a valid file name pattern for shipped language files.',
$pattern));
256 return self::$artifact_directory_for_tests
257 ?? rtrim($ilias_absolute_path,
'/') .
'/' . self::SHIPPED_ARTIFACT_DIRECTORY;
268 self::$artifact_directory_for_tests = $artifact_directory;
283 return rtrim($artifact_directory,
'/') .
'/'
284 . ($system_locale ? self::SYSTEM_LOCALE_BUILD_POINTER_FILE : self::BUILD_POINTER_FILE);
293 public static function buildDirectory(
string $artifact_directory,
string $build_id): string
295 if (preg_match(self::BUILD_ID_FORMAT, $build_id) !== 1) {
296 throw new \InvalidArgumentException(sprintf(
'"%s" is not a valid build id.', $build_id));
299 return rtrim($artifact_directory,
'/') .
'/' . $build_id;
304 return preg_match(self::BUILD_ID_FORMAT, $name) === 1;
313 public static function buildMoFile(
string $build_directory,
string $module,
string $lang_key): string
326 self::assertValidModule(
$module);
328 return rtrim($build_directory,
'/') .
'/keys/' .
$module .
'.php';
337 return rtrim($build_directory,
'/') .
'/locale';
347 self::assertValidModule(
$module);
348 self::assertValidLanguageKey($lang_key);
350 return $module .
'.' . $lang_key;
360 return self::shippedDomain(
$module, $lang_key) .
'.overlay';
373 self::assertValidModule(
$module);
374 self::assertValidLanguageKey($lang_key);
376 return rtrim($client_data_dir,
'/') .
'/lang/' .
$module .
'/' . $lang_key;
387 return self::overlayDirectory($client_data_dir, $directory->
getPrefix(), $lang_key)
388 .
'/' . sprintf(self::shippedFileNamePattern($directory), $lang_key) .
'.po';
396 return rtrim($overlay_directory,
'/') .
'/lock';
405 return rtrim($overlay_directory,
'/') .
'/current';
416 if (!self::isOverlayRevision($revision)) {
417 throw new \InvalidArgumentException(sprintf(
'"%s" is not a valid overlay revision.', $revision));
420 return rtrim($overlay_directory,
'/') .
'/' . $revision;
425 return preg_match(self::OVERLAY_REVISION_FORMAT, $name) === 1;
445 return rtrim($revision_directory,
'/') .
'/keys.json';
454 public static function takenOverFile(
string $client_data_dir,
string $lang_key): string
456 self::assertValidLanguageKey($lang_key);
458 return rtrim($client_data_dir,
'/') .
'/lang/taken-over.' . $lang_key .
'.json';
468 self::assertValidLanguageKey($lang_key);
470 return rtrim($client_data_dir,
'/') .
'/lang/.locks/taken-over.' . $lang_key .
'.lock';
483 self::assertValidModule(
$module);
485 return rtrim($client_data_dir,
'/') .
'/lang/' .
$module .
'/template.lock';
490 return preg_match(self::MODULE_FORMAT,
$module) === 1;
495 return preg_match(self::LANGUAGE_KEY_FORMAT, $lang_key) === 1;
503 if (!self::isValidModule(
$module)) {
504 throw new \InvalidArgumentException(sprintf(
'"%s" is not a valid module name.',
$module));
510 if (!self::isValidLanguageKey($lang_key)) {
511 throw new \InvalidArgumentException(sprintf(
'"%s" is not a valid language key.', $lang_key));
The single place that knows where the files of a module migrated to PO/MO live:
static assertValidModule(string $module)
static takenOverFile(string $client_data_dir, string $lang_key)
Record of the modules whose lng_data changes were taken over (see markLocalChangesTakenOver()): <clie...
static isOverlayRevision(string $name)
static string $artifact_directory_for_tests
const string BUILD_ID_FORMAT
static isValidModule(string $module)
static isBuildId(string $name)
static templateLockFile(string $client_data_dir, LanguageFileDirectory $directory)
The lock file serializing the writes of $directory's template (.pot) - shared by all languages,...
const string SYSTEM_LOCALE_BUILD_POINTER_FILE
static findShippedPoFiles(string $ilias_absolute_path, LanguageFileDirectory $directory)
The shipped .po files of $directory by language key, found via its file name pattern (see shippedFile...
static buildDirectory(string $artifact_directory, string $build_id)
artifacts/language/<build>: one complete build, bound with bindtextdomain() as it is (the C library l...
static overlayRevisionDirectory(string $overlay_directory, string $revision)
One compiled revision of the overlay in $overlay_directory: r-<hash>/, bound with bindtextdomain() as...
static shippedBasePath(string $ilias_absolute_path, LanguageFileDirectory $directory, string $lang_key)
Without extension; named by shippedFileNamePattern().
static buildLocaleDirectory(string $build_directory)
The directory with the locale NativeGettext activates (NativeGettext::LOCALE_NAME): <build>/locale,...
static shippedArtifactDirectory(string $ilias_absolute_path)
The directory Setup's build writes into (see ShippedTranslationsBuild), in the untracked artifacts/.
const string SHIPPED_TEMPLATES
const string OVERLAY_REVISION_FORMAT
static isValidLanguageKey(string $lang_key)
static buildMoFile(string $build_directory, string $module, string $lang_key)
The compiled catalog of $module for $lang_key: <build>/messages/LC_MESSAGES/<module>.
static overlayMoFile(string $revision_directory, string $module, string $lang_key)
The compiled overlay of $module for $lang_key in $revision_directory: r-<hash>/messages/LC_MESSAGES/<...
static isFoundWithoutGraph(string $ilias_absolute_path, LanguageFileDirectory $directory)
Whether findShippedTemplates() finds $directory's module.
static overlayDomain(string $module, string $lang_key)
The gettext domain of the overlay of $module for $lang_key: "<module>.<lang>.overlay".
static takenOverLockFile(string $client_data_dir, string $lang_key)
Lock for the read-modify-write of takenOverFile().
static resolveClientDataDir(?string $ilias_absolute_path=null)
The client data directory (CLIENT_DATA_DIR) of this installation, null if it cannot be determined or ...
static buildPointerFile(string $artifact_directory)
artifacts/language/current.json (current-system.json where NativeGettext::usesSystemLocale()): names ...
static overlayPoFile(string $client_data_dir, LanguageFileDirectory $directory, string $lang_key)
The overlay .po of $directory's module for $lang_key (the delta with its bookkeeping),...
static overlayDirectory(string $client_data_dir, string $module, string $lang_key)
The overlay of $module for $lang_key lives in <client data dir>/lang/<module>/<lang>/: the ....
static templateFileName(string $pattern, string $module)
The file name of the template (.pot) for the pattern $pattern of $module: the pattern without "%s" an...
static overlayLockFile(string $overlay_directory)
The lock file serializing the writes of the overlay in $overlay_directory.
static useArtifactDirectoryForTests(?string $artifact_directory)
Makes shippedArtifactDirectory() return $artifact_directory (null: the default) - for tests only,...
const string SHIPPED_ARTIFACT_DIRECTORY
const string MODULE_FORMAT
A module name as part of a file name and gettext domain "<module>.<lang>": no ".",...
static assertValidShippedFileNamePattern(string $pattern)
static fromDataDirAndClientId(?string $data_dir, ?string $client_id)
Composes the client data directory from its two parts (e.g.
static overlayKeysFile(string $revision_directory)
The identifiers the overlay revision $revision_directory has a value for: r-<hash>/keys....
static shippedFileNamePattern(LanguageFileDirectory $directory)
The name of $directory's shipped .po without ".po", with "%s" for the language key: its own pattern (...
static buildPointerFileOf(string $artifact_directory, bool $system_locale)
The pointer of the builds made with ($system_locale) or without a system locale.
static buildKeysFile(string $build_directory, string $module)
The identifiers of $module in the build, the same for every language: <build>/keys/<module>....
static shippedDomain(string $module, string $lang_key)
The gettext domain of the shipped state of $module for $lang_key: "<module>.<lang>".
static shippedDirectoryPath(string $ilias_absolute_path, LanguageFileDirectory $directory)
const string BUILD_POINTER_FILE
static overlayCurrentFile(string $overlay_directory)
The file naming the revision (see overlayRevisionDirectory()) of the overlay in $overlay_directory th...
static findShippedTemplates(string $ilias_absolute_path)
Module => lang/ directory of its <module>.pot; works without the component graph (Setup).
static shippedTemplatePath(string $ilias_absolute_path, LanguageFileDirectory $directory)
The template (.pot) next to the shipped .po files, see templateFileName().
static assertValidLanguageKey(string $lang_key)
const string LANGUAGE_KEY_FORMAT
static usesSystemLocale()
macOS/BSD: activate() uses a SYSTEM_LOCALES entry, their C library ignores LOCPATH.
const string CATALOG_DIRECTORY
if(!isset($arguments[0])) if(count( $arguments) > 3) if(! $remove_from_lang &&isset($arguments[2]) &&!is_dir($arguments[2])) $module
A directory of language files with a path and a prefix for them.
Optional addition to LanguageFileDirectory for shipped .po files not named <prefix>_<lang>....