<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][13936] trunk/src/bp-core: i18n: bring back custom locations for translation files</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://buddypress.trac.wordpress.org/changeset/13936">13936</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/13936","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>imath</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-06-24 02:05:55 +0000 (Mon, 24 Jun 2024)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>i18n: bring back custom locations for translation files

Prior to WordPress 4.6, it was possible to completely override the translation file with a custom one from one of the `'buddypress_locale_locations'` filterable list items.

With WordPress 6.5 latest improvements about l10n, we are now able to bring these back. Making it easier for users to customize every BuddyPress strings should help them build match their community needs (e.g.: using sport/school/working/any other wording).

3 functions has been introduced:

-  `bp_get_custom_translation_file()` is looking for a file name into `'buddypress_locale_locations'` filterable list items.
- `bp_load_custom_translation_file()` is the `'load_translation_file'` filter callback for regular translation files.
- `bp_load_custom_script_translation_file()` is the `'load_script_translation_file'` filter callback for JavaScript translation files.

The `bp_core_load_buddypress_textdomain()` function has been deprecated as it was pretty useless since WordPress 4.6.

Props espellcaste

Fixes <a href="http://buddypress.trac.wordpress.org/ticket/9187">#9187</a>
Closes https://github.com/buddypress/buddypress/pull/316</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcbpcorebpcorefunctionsphp">trunk/src/bp-core/bp-core-functions.php</a></li>
<li><a href="#trunksrcbpcoredeprecated140php">trunk/src/bp-core/deprecated/14.0.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcbpcorebpcorefunctionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-core/bp-core-functions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-core/bp-core-functions.php   2024-06-23 06:04:43 UTC (rev 13935)
+++ trunk/src/bp-core/bp-core-functions.php     2024-06-24 02:05:55 UTC (rev 13936)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2484,51 +2484,124 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /** Miscellaneous hooks *******************************************************/
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Load the buddypress translation file for current language.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Looks for the requested file name into a list of custom language locations.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 1.0.2
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 14.0.0
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @see load_textdomain() for a description of return values.
- *
- * @return bool
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $file_name The file name.
+ * @return string A file path or an empty string if no files were found into custom language locations.
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function bp_core_load_buddypress_textdomain() {
-       $domain = 'buddypress';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function bp_get_custom_translation_file( $file_name = '' ) {
+       $file_path = '';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        /**
-        * Filters the locale to be loaded for the language files.
-        *
-        * @since 1.0.2
-        *
-        * @param string $value Current locale for the install.
-        */
-       $mofile_custom = sprintf( '%s-%s.mo', $domain, apply_filters( 'buddypress_locale', get_locale() ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $file_name ) {
+               /**
+                * Filters the locations to load language files from.
+                *
+                * Custom translation files can be put in:
+                * 1. `/wp-content/languages/plugins/buddypress`
+                * 2. `/wp-content/languages/buddypress`
+                * 3. `/wp-content/languages`
+                *
+                * @since 2.2.0
+                * @since 14.0.0 Adds a new location.
+                *
+                * @param array $value Array of directories to check for language files in.
+                */
+               $locations = apply_filters( 'buddypress_locale_locations',
+                       array(
+                               trailingslashit( WP_LANG_DIR . '/plugins/buddypress'  ),
+                               trailingslashit( WP_LANG_DIR . '/buddypress'  ),
+                               trailingslashit( WP_LANG_DIR ),
+                       )
+               );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        /**
-        * Filters the locations to load language files from.
-        *
-        * @since 2.2.0
-        *
-        * @param array $value Array of directories to check for language files in.
-        */
-       $locations = apply_filters( 'buddypress_locale_locations', array(
-               trailingslashit( WP_LANG_DIR . '/' . $domain  ),
-               trailingslashit( WP_LANG_DIR ),
-       ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Try custom locations in WP_LANG_DIR.
+               foreach ( $locations as $location ) {
+                       $custom_file = $location . $file_name;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Try custom locations in WP_LANG_DIR.
-       foreach ( $locations as $location ) {
-               if ( load_textdomain( 'buddypress', $location . $mofile_custom ) ) {
-                       return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Use the first found.
+                       if ( file_exists( $custom_file ) ) {
+                               $file_path = $custom_file;
+                               break;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Default to WP and glotpress.
-       return load_plugin_textdomain( $domain );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return $file_path;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-add_action( 'bp_core_loaded', 'bp_core_load_buddypress_textdomain' );
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Override translation file for current language.
+ *
+ * @since 14.0.0
+ *
+ * @param  string $file   Absolut path to the translation file to use.
+ * @param  string $domain The text domain to check against `buddypress`.
+ * @param  string $locale The current locale for the WordPress site.
+ * @return string Absolut path to the translation file to use.
+ */
+function bp_load_custom_translation_file( $file, $domain, $locale = '' ) {
+       $bp_domain = 'buddypress';
+
+       if ( $domain !== $bp_domain ) {
+               return $file;
+       }
+
+       if ( ! $locale ) {
+               $locale = determine_locale();
+       }
+
+       $mofile_custom = bp_get_custom_translation_file(
+               /**
+                * Filters the locale to be loaded for the language files.
+                *
+                * @since 1.0.2
+                *
+                * @param string $locale Current locale.
+                */
+               sprintf( '%s-%s.mo', $domain, apply_filters( 'buddypress_locale', $locale ) )
+       );
+
+       if ( $mofile_custom ) {
+               $file = $mofile_custom;
+       }
+
+       // Returns the translation file to use.
+       return $file;
+}
+add_filter( 'load_translation_file', 'bp_load_custom_translation_file', 10, 3 );
+
+/**
+ * Override script translation file for current language.
+ *
+ * @since 14.0.0
+ *
+ * @param string|false $file   Path to the translation file to load. False if there isn't one.
+ * @param string       $handle Name of the script to register a translation domain to.
+ * @param string       $domain The text domain.
+ * @return string Path to the translation file to load.
+ */
+function bp_load_custom_script_translation_file( $file, $handle, $domain ) {
+       $bp_domain = 'buddypress';
+
+       if ( $domain !== $bp_domain ) {
+               return $file;
+       }
+
+       $file_name   = wp_basename( $file );
+       $custom_file = bp_get_custom_translation_file( $file_name );
+
+       if ( $custom_file ) {
+               $file = $custom_file;
+       }
+
+       // Returns the translation file to use.
+       return $file;
+}
+add_filter( 'load_script_translation_file', 'bp_load_custom_script_translation_file', 10, 3 );
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * A JavaScript-free implementation of the search functions in BuddyPress.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 1.0.1
</span></span></pre></div>
<a id="trunksrcbpcoredeprecated140php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/bp-core/deprecated/14.0.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/bp-core/deprecated/14.0.php     2024-06-23 06:04:43 UTC (rev 13935)
+++ trunk/src/bp-core/deprecated/14.0.php       2024-06-24 02:05:55 UTC (rev 13936)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -84,3 +84,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'error'
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Load the buddypress translation file for current language.
+ *
+ * @since 1.0.2
+ * @deprecated 14.0.0
+ *
+ * @return bool
+ */
+function bp_core_load_buddypress_textdomain() {
+       _deprecated_function( __FUNCTION__, '14.0.0' );
+
+       return false;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>