2020-07-05 23:35:51 +00:00
/ *
2021-01-01 15:10:36 +00:00
* Copyright ( c ) 2019 - 2021 GeyserMC . http : //geysermc.org
2020-07-05 23:35:51 +00:00
*
2020-07-30 20:10:15 +00:00
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
2020-07-05 23:35:51 +00:00
*
2020-07-30 20:10:15 +00:00
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
2020-07-05 23:35:51 +00:00
*
2020-07-30 20:10:15 +00:00
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
2020-07-05 23:35:51 +00:00
*
2020-07-30 20:10:15 +00:00
* @author GeyserMC
* @link https : //github.com/GeyserMC/Geyser
2020-07-05 23:35:51 +00:00
* /
package org.geysermc.connector.utils ;
import org.geysermc.connector.GeyserConnector ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.nio.charset.StandardCharsets ;
import java.text.MessageFormat ;
import java.util.HashMap ;
import java.util.Locale ;
import java.util.Map ;
import java.util.Properties ;
public class LanguageUtils {
/ * *
* If we determine the locale that the user wishes to use , use that locale
* /
private static String CACHED_LOCALE ;
private static final Map < String , Properties > LOCALE_MAPPINGS = new HashMap < > ( ) ;
static {
// Load it as a backup in case something goes really wrong
if ( ! " en_US " . equals ( formatLocale ( getDefaultLocale ( ) ) ) ) { // getDefaultLocale() loads the locale automatically
loadGeyserLocale ( " en_US " ) ;
}
}
/ * *
* Loads a Geyser locale from resources , if the file doesn ' t exist it just logs a warning
*
* @param locale Locale to load
* /
public static void loadGeyserLocale ( String locale ) {
locale = formatLocale ( locale ) ;
2020-10-29 22:30:52 +00:00
// Don't load the locale if it's already loaded.
if ( LOCALE_MAPPINGS . containsKey ( locale ) ) return ;
2020-07-05 23:35:51 +00:00
InputStream localeStream = GeyserConnector . class . getClassLoader ( ) . getResourceAsStream ( " languages/texts/ " + locale + " .properties " ) ;
// Load the locale
if ( localeStream ! = null ) {
Properties localeProp = new Properties ( ) ;
try {
localeProp . load ( new InputStreamReader ( localeStream , StandardCharsets . UTF_8 ) ) ;
} catch ( Exception e ) {
throw new AssertionError ( getLocaleStringLog ( " geyser.language.load_failed " , locale ) , e ) ;
}
// Insert the locale into the mappings
LOCALE_MAPPINGS . put ( locale , localeProp ) ;
} else {
2020-07-06 01:13:28 +00:00
if ( GeyserConnector . getInstance ( ) ! = null & & GeyserConnector . getInstance ( ) . getLogger ( ) ! = null ) {
GeyserConnector . getInstance ( ) . getLogger ( ) . warning ( " Missing locale: " + locale ) ;
2020-07-05 23:35:51 +00:00
}
}
}
/ * *
* Get a formatted language string with the default locale for Geyser
*
* @param key Language string to translate
* @param values Values to put into the string
* @return Translated string or the original message if it was not found in the given locale
* /
public static String getLocaleStringLog ( String key , Object . . . values ) {
return getPlayerLocaleString ( key , getDefaultLocale ( ) , values ) ;
}
/ * *
* Get a formatted language string with the given locale for Geyser
*
* @param key Language string to translate
* @param locale Locale to translate to
* @param values Values to put into the string
* @return Translated string or the original message if it was not found in the given locale
* /
public static String getPlayerLocaleString ( String key , String locale , Object . . . values ) {
locale = formatLocale ( locale ) ;
Properties properties = LOCALE_MAPPINGS . get ( locale ) ;
2020-11-18 23:18:36 +00:00
String formatString = null ;
if ( properties ! = null ) {
formatString = properties . getProperty ( key ) ;
}
2020-07-05 23:35:51 +00:00
// Try and get the key from the default locale
if ( formatString = = null ) {
properties = LOCALE_MAPPINGS . get ( formatLocale ( getDefaultLocale ( ) ) ) ;
formatString = properties . getProperty ( key ) ;
}
// Try and get the key from en_US (this should only ever happen in development)
if ( formatString = = null ) {
properties = LOCALE_MAPPINGS . get ( " en_US " ) ;
formatString = properties . getProperty ( key ) ;
}
// Final fallback
if ( formatString = = null ) {
formatString = key ;
}
2020-08-10 20:44:20 +00:00
return MessageFormat . format ( formatString . replace ( " ' " , " '' " ) . replace ( " & " , " \ u00a7 " ) , values ) ;
2020-07-05 23:35:51 +00:00
}
/ * *
* Cleans up and formats a locale string
*
* @param locale The locale to format
* @return The formatted locale
* /
2020-10-29 22:30:52 +00:00
public static String formatLocale ( String locale ) {
2020-07-05 23:35:51 +00:00
try {
String [ ] parts = locale . toLowerCase ( ) . split ( " _ " ) ;
2020-07-30 20:07:59 +00:00
return parts [ 0 ] + " _ " + parts [ 1 ] . toUpperCase ( ) ;
2020-07-05 23:35:51 +00:00
} catch ( Exception e ) {
return locale ;
}
}
/ * *
* Get the default locale that Geyser should use
* @return the current default locale
* /
public static String getDefaultLocale ( ) {
if ( CACHED_LOCALE ! = null ) return CACHED_LOCALE ; // We definitely know the locale the user is using
String locale ;
boolean isValid = true ;
if ( GeyserConnector . getInstance ( ) ! = null & &
GeyserConnector . getInstance ( ) . getConfig ( ) ! = null & &
GeyserConnector . getInstance ( ) . getConfig ( ) . getDefaultLocale ( ) ! = null ) { // If the config option for getDefaultLocale does not equal null, use that
locale = formatLocale ( GeyserConnector . getInstance ( ) . getConfig ( ) . getDefaultLocale ( ) ) ;
if ( isValidLanguage ( locale ) ) {
CACHED_LOCALE = locale ;
return locale ;
} else {
isValid = false ;
}
}
locale = formatLocale ( Locale . getDefault ( ) . getLanguage ( ) + " _ " + Locale . getDefault ( ) . getCountry ( ) ) ;
if ( ! isValidLanguage ( locale ) ) { // Bedrock does not support this language
locale = " en_US " ;
2020-07-06 13:41:55 +00:00
loadGeyserLocale ( locale ) ;
2020-07-05 23:35:51 +00:00
}
if ( GeyserConnector . getInstance ( ) ! = null & &
GeyserConnector . getInstance ( ) . getConfig ( ) ! = null & & ( GeyserConnector . getInstance ( ) . getConfig ( ) . getDefaultLocale ( ) = = null | | ! isValid ) ) { // Means we should use the system locale for sure
CACHED_LOCALE = locale ;
}
return locale ;
}
/ * *
* Ensures that the given locale is supported by Bedrock
* @param locale the locale to validate
* @return true if the given locale is supported by Bedrock and by extension Geyser
* /
private static boolean isValidLanguage ( String locale ) {
boolean result = true ;
if ( FileUtils . class . getResource ( " /languages/texts/ " + locale + " .properties " ) = = null ) {
result = false ;
if ( GeyserConnector . getInstance ( ) ! = null & & GeyserConnector . getInstance ( ) . getLogger ( ) ! = null ) { // Could be too early for these to be initialized
2021-01-11 01:00:48 +00:00
if ( locale . equals ( " en_US " ) ) {
GeyserConnector . getInstance ( ) . getLogger ( ) . error ( " English locale not found in Geyser. Did you clone the submodules? (git submodule update --init) " ) ;
} else {
GeyserConnector . getInstance ( ) . getLogger ( ) . warning ( locale + " is not a valid Bedrock language. " ) ; // We can't translate this since we just loaded an invalid language
}
2020-07-05 23:35:51 +00:00
}
} else {
if ( ! LOCALE_MAPPINGS . containsKey ( locale ) ) {
loadGeyserLocale ( locale ) ;
}
}
return result ;
}
public static void init ( ) {
// no-op
}
}