2017-03-05 15:47:28 +01:00
/**************************************************************************/
/* resource_importer_csv_translation.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2017-02-02 00:41:05 +01:00
# include "resource_importer_csv_translation.h"
2017-03-05 15:47:28 +01:00
2021-06-11 14:51:48 +02:00
# include "core/io/file_access.h"
2018-09-11 18:13:45 +02:00
# include "core/io/resource_saver.h"
2021-01-16 16:28:54 +01:00
# include "core/string/optimized_translation.h"
2020-11-07 23:33:38 +01:00
# include "core/string/translation.h"
2017-02-02 00:41:05 +01:00
String ResourceImporterCSVTranslation : : get_importer_name ( ) const {
return " csv_translation " ;
}
String ResourceImporterCSVTranslation : : get_visible_name ( ) const {
return " CSV Translation " ;
}
2020-05-14 14:29:06 +02:00
2017-02-02 00:41:05 +01:00
void ResourceImporterCSVTranslation : : get_recognized_extensions ( List < String > * p_extensions ) const {
p_extensions - > push_back ( " csv " ) ;
}
String ResourceImporterCSVTranslation : : get_save_extension ( ) const {
2018-02-21 17:30:55 +01:00
return " " ; //does not save a single resource
2017-02-02 00:41:05 +01:00
}
String ResourceImporterCSVTranslation : : get_resource_type ( ) const {
2017-05-20 22:49:34 +02:00
return " Translation " ;
2017-02-02 00:41:05 +01:00
}
2022-05-13 15:04:37 +02:00
bool ResourceImporterCSVTranslation : : get_option_visibility ( const String & p_path , const String & p_option , const HashMap < StringName , Variant > & p_options ) const {
2017-02-02 00:41:05 +01:00
return true ;
}
int ResourceImporterCSVTranslation : : get_preset_count ( ) const {
return 0 ;
}
2020-05-14 14:29:06 +02:00
2017-02-02 00:41:05 +01:00
String ResourceImporterCSVTranslation : : get_preset_name ( int p_idx ) const {
return " " ;
}
2021-11-14 18:02:38 +01:00
void ResourceImporterCSVTranslation : : get_import_options ( const String & p_path , List < ImportOption > * r_options , int p_preset ) const {
2017-02-02 00:41:05 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " compress " ) , true ) ) ;
2017-08-27 17:14:09 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " delimiter " , PROPERTY_HINT_ENUM , " Comma,Semicolon,Tab " ) , 0 ) ) ;
2017-02-02 00:41:05 +01:00
}
2022-05-13 15:04:37 +02:00
Error ResourceImporterCSVTranslation : : import ( const String & p_source_file , const String & p_save_path , const HashMap < StringName , Variant > & p_options , List < String > * r_platform_variants , List < String > * r_gen_files , Variant * r_metadata ) {
2017-02-02 00:41:05 +01:00
bool compress = p_options [ " compress " ] ;
2017-08-27 17:14:09 +02:00
String delimiter ;
switch ( ( int ) p_options [ " delimiter " ] ) {
2020-05-10 13:00:47 +02:00
case 0 :
delimiter = " , " ;
break ;
case 1 :
delimiter = " ; " ;
break ;
case 2 :
delimiter = " \t " ;
break ;
2017-08-27 17:14:09 +02:00
}
2022-03-23 10:08:58 +01:00
Ref < FileAccess > f = FileAccess : : open ( p_source_file , FileAccess : : READ ) ;
ERR_FAIL_COND_V_MSG ( f . is_null ( ) , ERR_INVALID_PARAMETER , " Cannot open file from path ' " + p_source_file + " '. " ) ;
2017-02-02 00:41:05 +01:00
2017-08-27 17:14:09 +02:00
Vector < String > line = f - > get_csv_line ( delimiter ) ;
2017-08-27 08:48:48 +02:00
ERR_FAIL_COND_V ( line . size ( ) < = 1 , ERR_PARSE_ERROR ) ;
2017-02-02 00:41:05 +01:00
Vector < String > locales ;
2020-03-17 07:33:00 +01:00
Vector < Ref < Translation > > translations ;
2023-10-19 06:55:35 +02:00
HashSet < int > skipped_locales ;
2017-02-02 00:41:05 +01:00
for ( int i = 1 ; i < line . size ( ) ; i + + ) {
2021-09-23 13:08:50 +02:00
String locale = TranslationServer : : get_singleton ( ) - > standardize_locale ( line [ i ] ) ;
2017-02-02 00:41:05 +01:00
2023-11-07 10:10:50 +01:00
if ( line [ i ] . left ( 1 ) = = " _ " ) {
2023-10-19 06:55:35 +02:00
skipped_locales . insert ( i ) ;
2023-11-07 10:10:50 +01:00
continue ;
} else if ( locale . is_empty ( ) ) {
skipped_locales . insert ( i ) ;
ERR_CONTINUE_MSG ( true , vformat ( " Error importing CSV translation: Invalid locale format '%s', should be 'language_Script_COUNTRY_VARIANT@extra'. This column will be ignored. " , line [ i ] ) ) ;
2023-10-19 06:55:35 +02:00
}
2017-02-02 00:41:05 +01:00
locales . push_back ( locale ) ;
Ref < Translation > translation ;
2021-06-18 00:03:09 +02:00
translation . instantiate ( ) ;
2017-02-02 00:41:05 +01:00
translation - > set_locale ( locale ) ;
translations . push_back ( translation ) ;
}
2021-03-19 19:50:53 +01:00
do {
line = f - > get_csv_line ( delimiter ) ;
2017-02-02 00:41:05 +01:00
String key = line [ 0 ] ;
2021-12-09 10:42:46 +01:00
if ( ! key . is_empty ( ) ) {
2023-11-07 10:10:50 +01:00
ERR_CONTINUE_MSG ( line . size ( ) ! = locales . size ( ) + ( int ) skipped_locales . size ( ) + 1 , vformat ( " Error importing CSV translation: expected %d locale(s), but the '%s' key has %d locale(s). " , locales . size ( ) , key , line . size ( ) - 1 ) ) ;
2021-03-19 19:50:53 +01:00
2024-03-16 16:26:06 +01:00
int write_index = 0 ; // Keep track of translations written in case some locales are skipped.
2017-02-02 00:41:05 +01:00
for ( int i = 1 ; i < line . size ( ) ; i + + ) {
2023-10-19 06:55:35 +02:00
if ( skipped_locales . has ( i ) ) {
continue ;
}
2024-03-16 16:26:06 +01:00
translations . write [ write_index + + ] - > add_message ( key , line [ i ] . c_unescape ( ) ) ;
2017-02-02 00:41:05 +01:00
}
}
2021-03-19 19:50:53 +01:00
} while ( ! f - > eof_reached ( ) ) ;
2017-02-02 00:41:05 +01:00
for ( int i = 0 ; i < translations . size ( ) ; i + + ) {
Ref < Translation > xlt = translations [ i ] ;
if ( compress ) {
2021-01-16 16:28:54 +01:00
Ref < OptimizedTranslation > cxl = memnew ( OptimizedTranslation ) ;
2017-02-02 00:41:05 +01:00
cxl - > generate ( xlt ) ;
xlt = cxl ;
}
2017-06-16 20:42:18 +02:00
String save_path = p_source_file . get_basename ( ) + " . " + translations [ i ] - > get_locale ( ) + " .translation " ;
2017-02-02 00:41:05 +01:00
2022-06-03 01:33:42 +02:00
ResourceSaver : : save ( xlt , save_path ) ;
2017-02-02 00:41:05 +01:00
if ( r_gen_files ) {
r_gen_files - > push_back ( save_path ) ;
}
}
return OK ;
}
ResourceImporterCSVTranslation : : ResourceImporterCSVTranslation ( ) {
}