<commit_before>//
//	SwiftDate, Full featured Swift date library for parsing, validating, manipulating, and formatting dates and timezones.
//	Created by:				<NAME>
//	Main contributors:		<NAME>
//
//
//	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:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	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.

import Foundation

/// This class allows you to read and load a custom `.strings` file or a file generated by a gived `Locale` instance.
public class Localization {
	
	/// Translations file loaded from a custom `.strings` file.
	/// It has a valid value only if `Localization` is loaded from a file.
	private var translations: NSDictionary?
	
	/// Bundle for given locale instances
	private var bundle: Bundle?
	/// Locale instances loaded (only if initialized via Locale instance)
	private(set) var locale: Locale?
	
	
	/// Init `Localization` instance from a custom `.strings` file at given path
	///
	/// - Parameter path: path to a strings file
	/// - Throws: throw an exception if not valid `strings` file was loaded.
	public init(path: String) throws {
		guard let data = NSDictionary(contentsOfFile: path) else {
			throw DateError.InvalidLocalizationFile
		}
		translations = data
	}
	
	
	/// Initialize a new `Localization` from a given `LocaleName`
	///
	/// - Parameter name: name of locale
	public convenience init(locale name: LocaleName) {
		self.init(locale: name.locale)
	}
	
	
	/// Init `Localization` instance with a given `locale` instance
	///
	/// - Parameter locale: locale to load; if `nil` current `locale` is used instead.
	public init(locale: Locale?) {
		guard let locale = locale else {
			self.bundle = Localization.resourceBundle()
			self.locale = Locale.current
			return
		}
		
		self.locale = locale
		let resourceBundle = Localization.resourceBundle()!
		let localeID = locale.collatorIdentifier
		guard let innerLanguagePath = resourceBundle.path(forResource: localeID, ofType: "lproj") else {
			
			//fallback to language only
			if let languageCode = locale.languageCode {
				//example : get french traduction even though you are live in belgium
				if let localOnlyPath = resourceBundle.path(forResource: "\(languageCode)-\(languageCode.uppercased())"  , ofType: "lproj") {
					self.bundle = Bundle(path: localOnlyPath)
					return
				}
			}
			// fallback to english if language was not found
			let englishPath = resourceBundle.path(forResource: "en-US", ofType: "lproj")!
			self.bundle = Bundle(path: englishPath)
			return
		}
		self.bundle = Bundle(path: innerLanguagePath)
	}
	
	
	/// Get translated value for a given key
	///
	/// - Parameters:
	///   - key: key to search
	///   - defValue: default fallback value. By default is empty string.
	/// - Returns: translated value<commit_msg>Fixed an issue while loading current Locale<commit_after>//
//	SwiftDate, Full featured Swift date library for parsing, validating, manipulating, and formatting dates and timezones.
//	Created by:				<NAME>
//	Main contributors:		<NAME>
//
//
//	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:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	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.

import Foundation

/// This class allows you to read and load a custom `.strings` file or a file generated by a gived `Locale` instance.
public class Localization {
	
	/// Translations file loaded from a custom `.strings` file.
	/// It has a valid value only if `Localization` is loaded from a file.
	private var translations: NSDictionary?
	
	/// Bundle for given locale instances
	private var bundle: Bundle?
	/// Locale instances loaded (only if initialized via Locale instance)
	private(set) var locale: Locale?
	
	
	/// Init `Localization` instance from a custom `.strings` file at given path
	///
	/// - Parameter path: path to a strings file
	/// - Throws: throw an exception if not valid `strings` file was loaded.
	public init(path: String) throws {
		guard let data = NSDictionary(contentsOfFile: path) else {
			throw DateError.InvalidLocalizationFile
		}
		translations = data
	}
	
	
	/// Initialize a new `Localization` from a given `LocaleName`
	///
	/// - Parameter name: name of locale
	public convenience init(locale name: LocaleName) {
		self.init(locale: name.locale)
	}
	
	
	/// Init `Localization` instance with a given `locale` instance
	///
	/// - Parameter locale: locale to load; if `nil` current `locale` is used instead.
	public init(locale: Locale?) {
		self.locale = locale ?? Locale.current
		
		let resourceBundle = Localization.resourceBundle()!
		let localeID = self.locale!.collatorIdentifier
		guard let innerLanguagePath = resourceBundle.path(forResource: localeID, ofType: "lproj") else {
			
			//fallback to language only
			if let languageCode = self.locale!.languageCode {
				//example : get french traduction even though you are live in belgium
				if let localOnlyPath = resourceBundle.path(forResource: "\(languageCode)-\(languageCode.uppercased())"  , ofType: "lproj") {
					self.bundle = Bundle(path: localOnlyPath)
					return
				}
			}
			// fallback to english if language was not found
			let englishPath = resourceBundle.path(forResource: "en-US", ofType: "lproj")!
			self.bundle = Bundle(path: englishPath)
			return
		}
		self.bundle = Bundle(path: innerLanguagePath)
	}
	
	
	/// Get translated value for a given key
	///
	/// - Parameters:
	///   - key: key to search
	///   - defValue: default fallback value. By default is empty string.
	/// - Returns: translated value
{'fraction_non_alphanumeric': 0.09241641750475672, 'fraction_numerical': 0.0, 'mean_word_length': 3.46, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5983805', 'n_tokens_mistral': 2192, 'n_tokens_neox': 1981, 'n_words': 884}