Automattic\WooCommerce\Internal\Admin

Translations::build_and_save_translations │ private │ WC 1.0

Combine and save translations for a specific locale.

Note that this assumes \WP_Filesystem is already initialized with write access.

Method of the class: Translations{}

No Hooks.

Returns

null. Nothing (null).

Usage

// private - for code of main (parent) class only
$result = $this->build_and_save_translations( $language_dir, $plugin_domain, $locale );
$language_dir(string) (required)
Path to language files.
$plugin_domain(string) (required)
Text domain.
$locale(string) (required)
Locale being retrieved.

Translations::build_and_save_translations() code WC 11.2.1

private function build_and_save_translations( $language_dir, $plugin_domain, $locale ) {
	global $wp_filesystem;
	$translations_from_chunks = $this->get_translation_chunk_data( $language_dir, $plugin_domain, $locale );

	if ( empty( $translations_from_chunks ) ) {
		return;
	}

	$cache_filename          = $this->get_combined_translation_filename( $plugin_domain, $locale );
	$chunk_translations_json = wp_json_encode( $translations_from_chunks );

	// Publish via a temp file so readers do not observe a partial write; the fallback below
	// gives that up rather than leave the previous pack's file in place.
	$temp_path  = $language_dir . $cache_filename . '.' . wp_generate_password( 12, false ) . '.tmp';
	$cache_path = $language_dir . $cache_filename;
	$published  = false;

	if ( $wp_filesystem->put_contents( $temp_path, $chunk_translations_json ) ) {
		// Not WP_Filesystem_Direct::move(): it deletes the destination before renaming.
		if ( 'direct' === get_filesystem_method() ) {
			// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.rename_rename -- Atomic replace; failure handled below.
			$published = @rename( $temp_path, $cache_path );
		} else {
			// Remote filesystems: overwrite only when refreshing an existing file.
			$published = $wp_filesystem->move( $temp_path, $cache_path, $wp_filesystem->exists( $cache_path ) );
		}
	}

	if ( ! $published ) {
		/*
		 * Reached when the temp file could not be written, and when publishing it failed: the
		 * FTP filesystems ignore the $overwrite argument and return ftp_rename() as-is, so
		 * servers that refuse to rename onto an existing path end up here. Without an in-place
		 * overwrite the previous language pack's file would survive, and nothing would ever
		 * replace it: the on-demand rebuild only runs when the file is missing, and never on a
		 * remote filesystem.
		 */
		if ( ! $wp_filesystem->put_contents( $cache_path, $chunk_translations_json ) ) {
			/*
			 * An in-place write truncates the file before it can fail, so what survives may be
			 * invalid JSON. A missing file recovers on its own - the rebuild triggers on it and
			 * readers fall back to their own translation file - while a corrupt one is served
			 * as-is forever.
			 */
			$leftover = $wp_filesystem->exists( $cache_path ) ? $wp_filesystem->get_contents( $cache_path ) : false;
			if ( false !== $leftover && null === json_decode( $leftover, true ) ) {
				$wp_filesystem->delete( $cache_path, false, 'f' );
			}
		}

		// Without the type, FTPext::delete() falls through to ftp_rmdir() when the file is absent.
		$wp_filesystem->delete( $temp_path, false, 'f' );
	}
}