Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
46.67% covered (danger)
46.67%
35 / 75
0.00% covered (danger)
0.00%
0 / 3
CRAP
n/a
0 / 0
wpcomsh_wporg_to_wpcom_locale_mo_file
93.94% covered (success)
93.94%
31 / 33
0.00% covered (danger)
0.00%
0 / 1
14.04
wpcomsh_allow_en_locale_override
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
wpcomsh_use_wpcomsh_fallback_for_jetpack_mu_wpcom_text_domain
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
1<?php
2/**
3 * WPCOMSH internationalization file.
4 *
5 * @package wpcomsh
6 */
7
8/**
9 * Provides a fallback mofile that uses wpcom locale slugs instead of wporg locale slugs
10 * This is needed for WP.COM themes that have their translations bundled with the theme.
11 *
12 * @see p8yzl4-4c-p2
13 *
14 * @param string $mofile  .mo language file being loaded by load_textdomain().
15 * @param string $domain  Text domain.
16 * @return string $mofile same or alternate mo file.
17 */
18function wpcomsh_wporg_to_wpcom_locale_mo_file( $mofile, $domain = '' ) {
19    if ( file_exists( $mofile ) ) {
20        return $mofile;
21    }
22
23    if ( ! class_exists( 'GP_Locales' ) ) {
24        if ( ! defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || ! file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
25            return $mofile;
26        }
27
28        require JETPACK__GLOTPRESS_LOCALES_PATH;
29    }
30
31    $original_mo_basename = basename( $mofile, '.mo' );
32    $locale_slug          = $original_mo_basename;
33
34    $theme_root = function_exists( 'get_theme_root' )
35        ? wp_normalize_path( trailingslashit( get_theme_root() ) )
36        : '';
37
38    // On WP Cloud sites, get_template_directory() returns /wordpress/themes/pub...
39    // which is the actual path to the theme, symlinked from wp-content/themes.
40    // _load_textdomain_just_in_time sees that the folders don't match
41    // and builds the mo file as "{$path}{$domain}-{$locale}.mo", so we need to
42    // remove the domain prefix to get the locale.
43    $remove_domain_prefix_for_theme = is_string( $domain ) && '' !== $domain
44        && '' !== $theme_root
45        && str_starts_with( wp_normalize_path( $mofile ), $theme_root )
46        && str_starts_with( $original_mo_basename, $domain . '-' );
47
48    if ( $remove_domain_prefix_for_theme ) {
49        $locale_slug = str_replace( $domain . '-', '', $original_mo_basename );
50    }
51
52    // These locales are not in our GP_Locales file, so rewrite them.
53    $locale_mappings = array(
54        'de_DE_formal' => 'de_DE', // formal German
55    );
56
57    if ( isset( $locale_mappings[ $locale_slug ] ) ) {
58        $locale_slug = $locale_mappings[ $locale_slug ];
59    }
60
61    $locale_object = GP_Locales::by_field( 'wp_locale', $locale_slug );
62    if ( ! $locale_object ) {
63        return $mofile;
64    }
65
66    $locale_slug = $locale_object->slug;
67
68    // For these languages we have a different slug than WordPress.org.
69    $locale_mappings = array(
70        'nb' => 'no', // Norwegian BokmÃ¥l.
71    );
72
73    if ( isset( $locale_mappings[ $locale_slug ] ) ) {
74        $locale_slug = $locale_mappings[ $locale_slug ];
75    }
76
77    // phpcs:ignore WordPress.PHP.PregQuoteDelimiter.Missing
78    $mofile = preg_replace( '/' . preg_quote( $original_mo_basename ) . '\.mo$/', $locale_slug . '.mo', $mofile );
79    return $mofile;
80}
81add_filter( 'load_textdomain_mofile', 'wpcomsh_wporg_to_wpcom_locale_mo_file', 9999, 2 );
82
83// Load translations for wpcomsh itself via MO file.
84add_action(
85    'after_setup_theme',
86    function () {
87        load_theme_textdomain( 'wpcomsh', WP_LANG_DIR . '/mu-plugins' );
88        load_theme_textdomain( 'jetpack-mu-wpcom', WP_LANG_DIR . '/mu-plugins' );
89    }
90);
91
92/*
93 * Early deploy of this fix in Jetpack: https://github.com/Automattic/jetpack/pull/14797
94 * To be removed after the release of 8.5 (but things won't break with the Jetpack fix shipped).
95 */
96add_filter(
97    'load_script_textdomain_relative_path',
98    function ( $relative, $src ) {
99        if ( class_exists( 'Jetpack_Photon_Static_Assets_CDN' ) ) {
100            // Get the local path from a URL which was CDN'ed by cdnize_plugin_assets().
101            if ( preg_match( '#^' . preg_quote( Jetpack_Photon_Static_Assets_CDN::CDN, '#' ) . 'p/[^/]+/[^/]+/(.*)$#', $src, $m ) ) {
102                return $m[1];
103            }
104        }
105
106        return $relative;
107    },
108    10,
109    2
110);
111
112// Ensure use of the correct local path when loading the JavaScript translation file for a CDN'ed asset.
113add_filter(
114    'load_script_translation_file',
115    function ( $file, $handle, $domain ) {
116        global $wp_scripts;
117
118        if ( in_array( $domain, array( 'jetpack-mu-wpcom', 'wpcomsh' ), true ) ) {
119            return WP_LANG_DIR . '/mu-plugins/' . basename( $file );
120        }
121
122        if ( class_exists( 'Jetpack_Photon_Static_Assets_CDN' ) ) {
123            // This is a rewritten plugin URL, so load the language file from the plugins path.
124            if ( isset( $wp_scripts->registered[ $handle ] ) && wp_startswith( $wp_scripts->registered[ $handle ]->src, Jetpack_Photon_Static_Assets_CDN::CDN . 'p' ) ) {
125                return WP_LANG_DIR . '/plugins/' . basename( $file );
126            }
127        }
128        return $file;
129    },
130    10,
131    3
132);
133
134// end of https://github.com/Automattic/jetpack/pull/14797
135
136/**
137 * Always allow override of _locale to English by setting ?_locale=en_US in the URL.
138 * All sites will have English translations available.
139 *
140 * This is used by class.wpcom-jetpack-mapper-get-admin-menu.php on WPCOM, which lets A8C users in support sessions view
141 * Atomic sites in languages that might not be installed on that Atomic site. WPCOM requests menu items in English, then
142 * retrieves them from the Atomic side, then translates them before display.
143 *
144 * @see D59986-code
145 *
146 * @param string $locale_in Default locale.
147 *
148 * @return string
149 */
150function wpcomsh_allow_en_locale_override( $locale_in ) {
151    if ( ! empty( $_GET['_locale'] ) && 'en_US' === $_GET['_locale'] ) { // phpcs:ignore WordPress.Security
152        return 'en_US';
153    }
154    return $locale_in;
155}
156add_filter( 'pre_determine_locale', 'wpcomsh_allow_en_locale_override' );
157
158/**
159 * Filter to hook into the `gettext` filter for requests against the `jetpack-mu-wpcom`
160 * text domain, as those translations are loaded into the `wpcomsh` text domain.
161 *
162 * @see https://github.com/Automattic/wpcomsh/issues/1727
163 *
164 * @param string $translation The translated text.
165 * @param string $singular    The text to translate.
166 * @param string $domain      The text domain.
167 * @return string
168 */
169function wpcomsh_use_wpcomsh_fallback_for_jetpack_mu_wpcom_text_domain( $translation, $singular, $domain = 'default' ) {
170    if ( $domain !== 'jetpack-mu-wpcom' ) {
171        return $translation;
172    }
173
174    if ( $translation !== $singular ) {
175        return $translation;
176    }
177
178    // This is a low-level filter, and we trust that $singular is a string, so we can ignore these important warnings.
179    // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.LowLevelTranslationFunction
180    return translate( $singular, 'wpcomsh' );
181}
182add_filter( 'gettext', 'wpcomsh_use_wpcomsh_fallback_for_jetpack_mu_wpcom_text_domain', 10, 3 );