mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Add language target: simplified/traditional chinese
Ready for multilingualization. See /doc/EN/dev_guide/i18n_messages.md.
This commit is contained in:
parent
a30be5d40d
commit
842fe10353
17 changed files with 459 additions and 183 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -29,6 +29,16 @@ japanese = [
|
||||||
"erg_parser/japanese",
|
"erg_parser/japanese",
|
||||||
"erg_compiler/japanese",
|
"erg_compiler/japanese",
|
||||||
]
|
]
|
||||||
|
simplified_chinese = [
|
||||||
|
"erg_common/simplified_chinese",
|
||||||
|
"erg_parser/simplified_chinese",
|
||||||
|
"erg_compiler/simplified_chinese",
|
||||||
|
]
|
||||||
|
traditional_chinese = [
|
||||||
|
"erg_common/traditional_chinese",
|
||||||
|
"erg_parser/traditional_chinese",
|
||||||
|
"erg_compiler/traditional_chinese",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.2.5", path = "./compiler/erg_common" }
|
erg_common = { version = "0.2.5", path = "./compiler/erg_common" }
|
||||||
|
|
BIN
assets/screenshot_i18n_messages.png
Normal file
BIN
assets/screenshot_i18n_messages.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 208 KiB |
|
@ -14,6 +14,8 @@ homepage = "https://erg-lang.github.io/"
|
||||||
[features]
|
[features]
|
||||||
debug = []
|
debug = []
|
||||||
japanese = []
|
japanese = []
|
||||||
|
simplified_chinese = []
|
||||||
|
traditional_chinese = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
|
|
|
@ -58,8 +58,8 @@ impl DeserializeError {
|
||||||
0,
|
0,
|
||||||
fn_name!(),
|
fn_name!(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"the loaded .pyc file is broken",
|
"japanese" => "読み込んだ.pycファイルは破損しています",
|
||||||
"読み込んだ.pycファイルは破損しています"
|
"english" => "the loaded .pyc file is broken",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -69,14 +69,14 @@ impl DeserializeError {
|
||||||
0,
|
0,
|
||||||
fn_name!(),
|
fn_name!(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!(
|
"japanese" => format!(
|
||||||
|
"{}型オブジェクトを予期しましたが、 読み込んだオブジェクトは{}型です",
|
||||||
|
expect, found
|
||||||
|
),
|
||||||
|
"english" => format!(
|
||||||
"expect a {} object, but the deserialized object is {}",
|
"expect a {} object, but the deserialized object is {}",
|
||||||
expect, found
|
expect, found
|
||||||
),
|
),
|
||||||
format!(
|
|
||||||
"{}型オブジェクトを予期しましたが、 読み込んだオブジェクトは{}型です",
|
|
||||||
expect, found
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -228,8 +228,8 @@ impl Deserializer {
|
||||||
0,
|
0,
|
||||||
fn_name!(),
|
fn_name!(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("cannot deserialize this object: {}", other),
|
"japanese" => format!("このオブジェクトは復元できません: {}", other),
|
||||||
format!("このオブジェクトは復元できません: {}", other)
|
"english" => format!("cannot deserialize this object: {}", other),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,10 @@ impl Deserializer {
|
||||||
return Err(DeserializeError::new(
|
return Err(DeserializeError::new(
|
||||||
0,
|
0,
|
||||||
fn_name!(),
|
fn_name!(),
|
||||||
switch_lang!("failed to load bytes", "バイト列の読み込みに失敗しました"),
|
switch_lang!(
|
||||||
|
"japanese" => "バイト列の読み込みに失敗しました",
|
||||||
|
"english" => "failed to load bytes",
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let len = Self::deserialize_u32(v);
|
let len = Self::deserialize_u32(v);
|
||||||
|
|
|
@ -321,10 +321,16 @@ impl ErrorCore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
pub fn bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
||||||
Self::new(errno, CompilerSystemError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("this is a bug of Erg, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
errno,
|
||||||
format!("これはErgのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生")
|
CompilerSystemError,
|
||||||
), None)
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("これはErgのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生"),
|
||||||
|
"english" => format!("this is a bug of Erg, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,11 +58,17 @@ macro_rules! impl_display_for_enum_with_variant {
|
||||||
/// マクロはパラメータを展開しないので、format!のロスがなくなる
|
/// マクロはパラメータを展開しないので、format!のロスがなくなる
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! switch_lang {
|
macro_rules! switch_lang {
|
||||||
($en: expr, $jp: expr $(,)*) => {{
|
(
|
||||||
if cfg!(feature = "japanese") {
|
$should_english: literal => $msg: expr,
|
||||||
$jp
|
) => {{ $msg }};
|
||||||
|
(
|
||||||
|
$lang_name: literal => $msg: expr,
|
||||||
|
$($rest_lang_name: literal => $rest_msg: expr,)+
|
||||||
|
) => {{
|
||||||
|
if cfg!(feature = $lang_name) {
|
||||||
|
$msg
|
||||||
} else {
|
} else {
|
||||||
$en
|
switch_lang!($($rest_lang_name => $rest_msg,)+)
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,8 +326,8 @@ impl ValueObj {
|
||||||
panic!(
|
panic!(
|
||||||
"{}",
|
"{}",
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("this object cannot be serialized: {other}"),
|
"japanese" => format!("このオブジェクトはシリアライズできません: {other}"),
|
||||||
format!("このオブジェクトはシリアライズできません: {other}")
|
"english" => format!("this object cannot be serialized: {other}"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ homepage = "https://erg-lang.github.io/"
|
||||||
# when "debug" feature is turned on, that of parser will also be turned on.
|
# when "debug" feature is turned on, that of parser will also be turned on.
|
||||||
debug = [ "erg_common/debug", "erg_parser/debug" ]
|
debug = [ "erg_common/debug", "erg_parser/debug" ]
|
||||||
japanese = [ "erg_common/japanese", "erg_parser/japanese" ]
|
japanese = [ "erg_common/japanese", "erg_parser/japanese" ]
|
||||||
|
simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_chinese" ]
|
||||||
|
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.2.5", path = "../erg_common" }
|
erg_common = { version = "0.2.5", path = "../erg_common" }
|
||||||
|
|
|
@ -138,10 +138,20 @@ impl CompileError {
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
line: u32,
|
line: u32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("this is a bug of the Erg compiler, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
ErrorCore::new(
|
||||||
format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生")
|
errno,
|
||||||
), None), input, "".into())
|
CompilerSystemError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生"),
|
||||||
|
"english" => format!("this is a bug of the Erg compiler, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
"".into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_bug(
|
pub fn stack_bug(
|
||||||
|
@ -151,14 +161,24 @@ impl CompileError {
|
||||||
block_id: usize,
|
block_id: usize,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(ErrorCore::new(0, CompilerSystemError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("the number of elements in the stack is invalid (num of elems: {stack_len}, block id: {block_id})\n\
|
ErrorCore::new(
|
||||||
|
0,
|
||||||
|
CompilerSystemError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("スタックの要素数が異常です (要素数: {stack_len}, ブロックID: {block_id})\n\
|
||||||
|
これはコンパイラのバグです、開発者に報告して下さい (https://github.com/...)\n\
|
||||||
|
{fn_name}より発生"),
|
||||||
|
"english" => format!("the number of elements in the stack is invalid (num of elems: {stack_len}, block id: {block_id})\n\
|
||||||
this is a bug of the Erg compiler, please report it (https://github.com/...)\n\
|
this is a bug of the Erg compiler, please report it (https://github.com/...)\n\
|
||||||
caused from: {fn_name}"),
|
caused from: {fn_name}"),
|
||||||
format!("スタックの要素数が異常です (要素数: {stack_len}, ブロックID: {block_id})\n\
|
),
|
||||||
これはコンパイラのバグです、開発者に報告して下さい (https://github.com/...)\n\
|
None,
|
||||||
{fn_name}より発生")
|
),
|
||||||
), None), input, "".into())
|
input,
|
||||||
|
"".into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: Str) -> Self {
|
pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: Str) -> Self {
|
||||||
|
@ -168,8 +188,9 @@ impl CompileError {
|
||||||
FeatureError,
|
FeatureError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("this feature({name}) is not implemented yet"),
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
format!("この機能({name})はまだ正式に提供されていません")
|
"simplified_chinese" => format!("该功能({name})还没有正式提供"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -195,10 +216,19 @@ impl TyCheckError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checker_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
pub fn checker_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
||||||
Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("this is a bug of the Erg compiler, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
ErrorCore::new(
|
||||||
format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生")
|
errno,
|
||||||
), None), "".into())
|
CompilerSystemError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生"),
|
||||||
|
"english" => format!("this is a bug of the Erg compiler, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
"".into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn feature_error(loc: Location, name: &str, caused_by: Str) -> Self {
|
pub fn feature_error(loc: Location, name: &str, caused_by: Str) -> Self {
|
||||||
|
@ -208,8 +238,8 @@ impl TyCheckError {
|
||||||
FeatureError,
|
FeatureError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("this feature({name}) is not implemented yet"),
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
format!("この機能({name})はまだ正式に提供されていません")
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -238,8 +268,8 @@ impl TyCheckError {
|
||||||
NameError,
|
NameError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{name} is already declared"),
|
"japanese" => format!("{name}は既に宣言されています"),
|
||||||
format!("{name}は既に宣言されています")
|
"english" => format!("{name} is already declared"),
|
||||||
),
|
),
|
||||||
Option::<Str>::None,
|
Option::<Str>::None,
|
||||||
),
|
),
|
||||||
|
@ -255,12 +285,18 @@ impl TyCheckError {
|
||||||
found_t: &Type,
|
found_t: &Type,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let name = readable_name(name);
|
let name = readable_name(name);
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc,
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
0,
|
||||||
|
TypeError,
|
||||||
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{name} was declared as {GREEN}{spec_t}{RESET}, but an {RED}{found_t}{RESET} object is assigned"),
|
"japanese" => format!("{name}は{GREEN}{spec_t}{RESET}型として宣言されましたが、{RED}{found_t}{RESET}型のオブジェクトが代入されています"),
|
||||||
format!("{name}は{GREEN}{spec_t}{RESET}型として宣言されましたが、{RED}{found_t}{RESET}型のオブジェクトが代入されています")
|
"english" => format!("{name} was declared as {GREEN}{spec_t}{RESET}, but an {RED}{found_t}{RESET} object is assigned"),
|
||||||
), Option::<Str>::None),
|
),
|
||||||
caused_by
|
Option::<Str>::None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,8 +308,8 @@ impl TyCheckError {
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("the type of {name} is not specified"),
|
"japanese" => format!("{name}の型が指定されていません"),
|
||||||
format!("{name}の型が指定されていません")
|
"english" => format!("the type of {name} is not specified"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -291,8 +327,8 @@ impl TyCheckError {
|
||||||
let hint = similar_name.map(|n| {
|
let hint = similar_name.map(|n| {
|
||||||
let n = readable_name(n);
|
let n = readable_name(n);
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("exists a similar name variable: {n}"),
|
"japanese" => format!("似た名前の変数があります: {n}"),
|
||||||
format!("似た名前の変数があります: {n}")
|
"english" => format!("exists a similar name variable: {n}"),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
@ -302,8 +338,8 @@ impl TyCheckError {
|
||||||
NameError,
|
NameError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{RED}{name}{RESET} is not defined"),
|
"japanese" => format!("{RED}{name}{RESET}という変数は定義されていません"),
|
||||||
format!("{RED}{name}{RESET}という変数は定義されていません")
|
"english" => format!("{RED}{name}{RESET} is not defined"),
|
||||||
),
|
),
|
||||||
hint,
|
hint,
|
||||||
),
|
),
|
||||||
|
@ -321,8 +357,8 @@ impl TyCheckError {
|
||||||
let hint = similar_name.map(|n| {
|
let hint = similar_name.map(|n| {
|
||||||
let n = readable_name(n);
|
let n = readable_name(n);
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("has a similar name attribute: {n}"),
|
"japanese" => format!("似た名前の属性があります: {n}"),
|
||||||
format!("似た名前の属性があります: {n}")
|
"english" => format!("has a similar name attribute: {n}"),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
@ -332,8 +368,8 @@ impl TyCheckError {
|
||||||
AttributeError,
|
AttributeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{obj_t} object has no attribute {RED}{name}{RESET}"),
|
"japanese" => format!("{obj_t}型オブジェクトに{RED}{name}{RESET}という属性はありません"),
|
||||||
format!("{obj_t}型オブジェクトに{RED}{name}{RESET}という属性はありません")
|
"english" => format!("{obj_t} object has no attribute {RED}{name}{RESET}"),
|
||||||
),
|
),
|
||||||
hint,
|
hint,
|
||||||
),
|
),
|
||||||
|
@ -353,12 +389,12 @@ impl TyCheckError {
|
||||||
NotImplementedError,
|
NotImplementedError,
|
||||||
callee.loc(),
|
callee.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!(
|
"japanese" => format!(
|
||||||
|
"{callee}は{param_ts}を引数に取る呼び出し可能オブジェクトではありません"
|
||||||
|
),
|
||||||
|
"english" => format!(
|
||||||
"{callee} is not a Callable object that takes {param_ts} as an argument"
|
"{callee} is not a Callable object that takes {param_ts} as an argument"
|
||||||
),
|
),
|
||||||
format!(
|
|
||||||
"{callee}は{param_ts}を引数に取る呼び出し可能オブジェクトではありません"
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -373,10 +409,19 @@ impl TyCheckError {
|
||||||
expect: &Type,
|
expect: &Type,
|
||||||
found: &Type,
|
found: &Type,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("the type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("{name}の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{name}の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}"),
|
||||||
|
"english" => format!("the type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type_error(
|
pub fn return_type_error(
|
||||||
|
@ -386,10 +431,19 @@ impl TyCheckError {
|
||||||
expect: &Type,
|
expect: &Type,
|
||||||
found: &Type,
|
found: &Type,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("the return type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("{name}の戻り値の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{name}の戻り値の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}"),
|
||||||
|
"english" => format!("the return type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uninitialized_error(loc: Location, caused_by: Str, name: &str, t: &Type) -> Self {
|
pub fn uninitialized_error(loc: Location, caused_by: Str, name: &str, t: &Type) -> Self {
|
||||||
|
@ -399,8 +453,8 @@ impl TyCheckError {
|
||||||
NameError,
|
NameError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{name}: {t} is not initialized"),
|
"japanese" => format!("{name}: {t}は初期化されていません"),
|
||||||
format!("{name}: {t}は初期化されていません")
|
"english" => format!("{name}: {t} is not initialized"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -409,10 +463,19 @@ impl TyCheckError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn argument_error(loc: Location, caused_by: Str, expect: usize, found: usize) -> Self {
|
pub fn argument_error(loc: Location, caused_by: Str, expect: usize, found: usize) -> Self {
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("the number of positional arguments is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("ポジショナル引数の数が違います。\n予期した個数: {GREEN}{expect}{RESET}\n与えられた個数: {RED}{found}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("ポジショナル引数の数が違います。\n予期した個数: {GREEN}{expect}{RESET}\n与えられた個数: {RED}{found}{RESET}"),
|
||||||
|
"english" => format!("the number of positional arguments is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_error(loc: Location, caused_by: Str, expr_t: &Type) -> Self {
|
pub fn match_error(loc: Location, caused_by: Str, expr_t: &Type) -> Self {
|
||||||
|
@ -422,8 +485,8 @@ impl TyCheckError {
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("not all patterns of type {expr_t} are covered"),
|
"japanese" => format!("{expr_t}型の全パターンを網羅していません"),
|
||||||
format!("{expr_t}型の全パターンを網羅していません")
|
"english" => format!("not all patterns of type {expr_t} are covered"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -438,8 +501,8 @@ impl TyCheckError {
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("failed to infer the type of {expr}"),
|
"japanese" => format!("{expr}の型が推論できません"),
|
||||||
format!("{expr}の型が推論できません")
|
"english" => format!("failed to infer the type of {expr}"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -463,8 +526,8 @@ impl TyCheckError {
|
||||||
AssignError,
|
AssignError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("cannot assign twice to the immutable variable {name}"),
|
"japanese" => format!("定数{name}には再代入できません"),
|
||||||
format!("定数{name}には再代入できません")
|
"english" => format!("cannot assign twice to the immutable variable {name}"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -487,18 +550,18 @@ impl TyCheckError {
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!(
|
"japanese" => format!(
|
||||||
|
"{name}に渡された引数の数が多すぎます。
|
||||||
|
必要な引数の合計数: {GREEN}{params_len}{RESET}個
|
||||||
|
渡された引数の数: {RED}{pos_args_len}{RESET}個
|
||||||
|
キーワード引数の数: {RED}{kw_args_len}{RESET}個"
|
||||||
|
),
|
||||||
|
"english" => format!(
|
||||||
"too many arguments for {name}:
|
"too many arguments for {name}:
|
||||||
total expected params: {GREEN}{params_len}{RESET}
|
total expected params: {GREEN}{params_len}{RESET}
|
||||||
passed positional args: {RED}{pos_args_len}{RESET}
|
passed positional args: {RED}{pos_args_len}{RESET}
|
||||||
passed keyword args: {RED}{kw_args_len}{RESET}"
|
passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
),
|
),
|
||||||
format!(
|
|
||||||
"{name}に渡された引数の数が多すぎます。
|
|
||||||
必要な引数の合計数: {GREEN}{params_len}{RESET}個
|
|
||||||
渡された引数の数: {RED}{pos_args_len}{RESET}個
|
|
||||||
キーワード引数の数: {RED}{kw_args_len}{RESET}個"
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -519,8 +582,8 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{name}'s argument {RED}{arg_name}{RESET} is passed multiple times"),
|
"japanese" => format!("{name}の引数{RED}{arg_name}{RESET}が複数回渡されています"),
|
||||||
format!("{name}の引数{RED}{arg_name}{RESET}が複数回渡されています")
|
"english" => format!("{name}'s argument {RED}{arg_name}{RESET} is passed multiple times"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -541,8 +604,8 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
TypeError,
|
TypeError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{name} got unexpected keyword argument {RED}{param_name}{RESET}"),
|
"japanese" => format!("{name}には予期しないキーワード引数{RED}{param_name}{RESET}が渡されています"),
|
||||||
format!("{name}には予期しないキーワード引数{RED}{param_name}{RESET}が渡されています")
|
"english" => format!("{name} got unexpected keyword argument {RED}{param_name}{RESET}"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -558,8 +621,8 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
UnusedWarning,
|
UnusedWarning,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("{YELLOW}{name}{RESET} is not used"),
|
"japanese" => format!("{YELLOW}{name}{RESET}は使用されていません"),
|
||||||
format!("{YELLOW}{name}{RESET}は使用されていません")
|
"english" => format!("{YELLOW}{name}{RESET} is not used"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -580,10 +643,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
(None, Some(r)) => r,
|
(None, Some(r)) => r,
|
||||||
(None, None) => Location::Unknown,
|
(None, None) => Location::Unknown,
|
||||||
};
|
};
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("unification failed:\nlhs: {YELLOW}{lhs_t}{RESET}\nrhs: {YELLOW}{rhs_t}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("型の単一化に失敗しました:\n左辺: {YELLOW}{lhs_t}{RESET}\n右辺: {YELLOW}{rhs_t}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("型の単一化に失敗しました:\n左辺: {YELLOW}{lhs_t}{RESET}\n右辺: {YELLOW}{rhs_t}{RESET}"),
|
||||||
|
"english" => format!("unification failed:\nlhs: {YELLOW}{lhs_t}{RESET}\nrhs: {YELLOW}{rhs_t}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn re_unification_error(
|
pub fn re_unification_error(
|
||||||
|
@ -599,10 +671,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
(None, Some(r)) => r,
|
(None, Some(r)) => r,
|
||||||
(None, None) => Location::Unknown,
|
(None, None) => Location::Unknown,
|
||||||
};
|
};
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("re-unification failed:\nlhs: {YELLOW}{lhs_t}{RESET}\nrhs: {YELLOW}{rhs_t}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("型の再単一化に失敗しました:\n左辺: {YELLOW}{lhs_t}{RESET}\n右辺: {YELLOW}{rhs_t}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("型の再単一化に失敗しました:\n左辺: {YELLOW}{lhs_t}{RESET}\n右辺: {YELLOW}{rhs_t}{RESET}"),
|
||||||
|
"english" => format!("re-unification failed:\nlhs: {YELLOW}{lhs_t}{RESET}\nrhs: {YELLOW}{rhs_t}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtyping_error(
|
pub fn subtyping_error(
|
||||||
|
@ -618,17 +699,35 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
(None, Some(r)) => r,
|
(None, Some(r)) => r,
|
||||||
(None, None) => Location::Unknown,
|
(None, None) => Location::Unknown,
|
||||||
};
|
};
|
||||||
Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!(
|
Self::new(
|
||||||
format!("subtype constraints cannot be satisfied:\nsubtype: {YELLOW}{sub_t}{RESET}\nsupertype: {YELLOW}{sup_t}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("部分型制約を満たせません:\nサブタイプ: {YELLOW}{sub_t}{RESET}\nスーパータイプ: {YELLOW}{sup_t}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("部分型制約を満たせません:\nサブタイプ: {YELLOW}{sub_t}{RESET}\nスーパータイプ: {YELLOW}{sup_t}{RESET}"),
|
||||||
|
"english" => format!("subtype constraints cannot be satisfied:\nsubtype: {YELLOW}{sub_t}{RESET}\nsupertype: {YELLOW}{sup_t}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pred_unification_error(lhs: &Predicate, rhs: &Predicate, caused_by: Str) -> Self {
|
pub fn pred_unification_error(lhs: &Predicate, rhs: &Predicate, caused_by: Str) -> Self {
|
||||||
Self::new(ErrorCore::new(0, TypeError, Location::Unknown, switch_lang!(
|
Self::new(
|
||||||
format!("predicate unification failed:\nlhs: {YELLOW}{lhs}{RESET}\nrhs: {YELLOW}{rhs}{RESET}"),
|
ErrorCore::new(
|
||||||
format!("述語式の単一化に失敗しました:\n左辺: {YELLOW}{lhs}{RESET}\n右辺: {YELLOW}{rhs}{RESET}")
|
0,
|
||||||
), None), caused_by)
|
TypeError,
|
||||||
|
Location::Unknown,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("述語式の単一化に失敗しました:\n左辺: {YELLOW}{lhs}{RESET}\n右辺: {YELLOW}{rhs}{RESET}"),
|
||||||
|
"english" => format!("predicate unification failed:\nlhs: {YELLOW}{lhs}{RESET}\nrhs: {YELLOW}{rhs}{RESET}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_effect<S: Into<Str>>(expr: &Expr, caused_by: S) -> Self {
|
pub fn has_effect<S: Into<Str>>(expr: &Expr, caused_by: S) -> Self {
|
||||||
|
@ -638,8 +737,8 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
HasEffect,
|
HasEffect,
|
||||||
expr.loc(),
|
expr.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("this expression causes a side-effect"),
|
"japanese" => format!("この式には副作用があります"),
|
||||||
format!("この式には副作用があります")
|
"english" => format!("this expression causes a side-effect"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
@ -659,14 +758,14 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
MoveError,
|
MoveError,
|
||||||
name_loc,
|
name_loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!(
|
"japanese" => format!(
|
||||||
|
"{RED}{name}{RESET}は{}行目ですでに移動されています",
|
||||||
|
moved_loc.ln_begin().unwrap()
|
||||||
|
),
|
||||||
|
"english" => format!(
|
||||||
"{RED}{name}{RESET} was moved in line {}",
|
"{RED}{name}{RESET} was moved in line {}",
|
||||||
moved_loc.ln_begin().unwrap()
|
moved_loc.ln_begin().unwrap()
|
||||||
),
|
),
|
||||||
format!(
|
|
||||||
"{RED}{name}{RESET}は{}行目ですでに移動されています",
|
|
||||||
moved_loc.ln_begin().unwrap()
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
|
|
@ -62,13 +62,13 @@ impl ASTLowerer {
|
||||||
expr.loc(),
|
expr.loc(),
|
||||||
self.ctx.name.clone(),
|
self.ctx.name.clone(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"the evaluation result of the expression is not used",
|
"japanese" => "式の評価結果が使われていません",
|
||||||
"式の評価結果が使われていません",
|
"english" => "the evaluation result of the expression is not used",
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"if you don't use the value, use `discard` function",
|
"japanese" => "値を使わない場合は、discard関数を使用してください",
|
||||||
"値を使わない場合は、discard関数を使用してください",
|
"english" => "if you don't use the value, use `discard` function",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -12,6 +12,8 @@ homepage = "https://erg-lang.github.io/"
|
||||||
[features]
|
[features]
|
||||||
debug = [ "erg_common/debug" ]
|
debug = [ "erg_common/debug" ]
|
||||||
japanese = [ "erg_common/japanese" ]
|
japanese = [ "erg_common/japanese" ]
|
||||||
|
simplified_chinese = [ "erg_common/simplified_chinese" ]
|
||||||
|
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.2.5", path = "../erg_common" }
|
erg_common = { version = "0.2.5", path = "../erg_common" }
|
||||||
|
|
|
@ -21,10 +21,16 @@ impl LexError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
||||||
Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!(
|
Self::new(ErrorCore::new(
|
||||||
format!("this is a bug of the Erg compiler, please report it to https://github.com/mtshiba/erg\ncaused from: {fn_name}:{line}"),
|
errno,
|
||||||
format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/mtshiba/erg)\n{fn_name}:{line}より発生")
|
CompilerSystemError,
|
||||||
), None))
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/mtshiba/erg)\n{fn_name}:{line}より発生"),
|
||||||
|
"english" => format!("this is a bug of the Erg compiler, please report it to https://github.com/mtshiba/erg\ncaused from: {fn_name}:{line}"),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn feature_error(errno: usize, loc: Location, name: &str) -> Self {
|
pub fn feature_error(errno: usize, loc: Location, name: &str) -> Self {
|
||||||
|
@ -33,8 +39,9 @@ impl LexError {
|
||||||
FeatureError,
|
FeatureError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("this feature({name}) is not implemented yet"),
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
format!("この機能({name})はまだ正式に提供されていません")
|
"simplified_chinese" => format!("该功能({name})还没有正式提供"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
|
@ -45,7 +52,11 @@ impl LexError {
|
||||||
errno,
|
errno,
|
||||||
SyntaxError,
|
SyntaxError,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!("invalid syntax", "不正な構文です"),
|
switch_lang!(
|
||||||
|
"japanese" => "不正な構文です",
|
||||||
|
"simplified_chinese" => "无效的语法",
|
||||||
|
"english" => "invalid syntax",
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,8 +266,8 @@ impl Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
comment.loc(),
|
comment.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"invalid unicode character (bi-directional override) in comments",
|
"japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています",
|
||||||
"不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています"
|
"english" => "invalid unicode character (bi-directional override) in comments",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
@ -298,7 +298,10 @@ impl Lexer /*<'a>*/ {
|
||||||
Some(Err(LexError::syntax_error(
|
Some(Err(LexError::syntax_error(
|
||||||
0,
|
0,
|
||||||
space.loc(),
|
space.loc(),
|
||||||
switch_lang!("invalid indent", "インデントが不正です"),
|
switch_lang!(
|
||||||
|
"japanese" => "インデントが不正です",
|
||||||
|
"english" => "invalid indent",
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
} else if self.prev_token.is(Newline) {
|
} else if self.prev_token.is(Newline) {
|
||||||
|
@ -317,11 +320,14 @@ impl Lexer /*<'a>*/ {
|
||||||
return Some(Err(LexError::syntax_error(
|
return Some(Err(LexError::syntax_error(
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!("indentation is too deep", "インデントが深すぎます"),
|
switch_lang!(
|
||||||
|
"japanese" => "インデントが深すぎます",
|
||||||
|
"english" => "indentation is too deep",
|
||||||
|
),
|
||||||
Some(
|
Some(
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"The code is too complicated. Please split the process.",
|
"japanese" => "コードが複雑すぎます。処理を分割してください",
|
||||||
"コードが複雑すぎます。処理を分割してください"
|
"english" => "The code is too complicated. Please split the process",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
@ -359,7 +365,10 @@ impl Lexer /*<'a>*/ {
|
||||||
Some(Err(LexError::syntax_error(
|
Some(Err(LexError::syntax_error(
|
||||||
0,
|
0,
|
||||||
invalid_dedent.loc(),
|
invalid_dedent.loc(),
|
||||||
switch_lang!("invalid indent", "インデントが不正です"),
|
switch_lang!(
|
||||||
|
"japanese" => "インデントが不正です",
|
||||||
|
"english" => "invalid indent",
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -529,8 +538,8 @@ impl Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"invalid unicode character (bi-directional override) in string literal",
|
"japanese" => "不正なユニコード文字(双方向オーバーライド)が文字列中に使用されています",
|
||||||
"不正なユニコード文字(双方向オーバーライド)が文字列中に使用されています"
|
"english" => "invalid unicode character (bi-directional override) in string literal",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
@ -542,8 +551,8 @@ impl Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"the string is not closed by \"",
|
"japanese" => "文字列が\"によって閉じられていません",
|
||||||
"文字列が\"によって閉じられていません"
|
"english" => "the string is not closed by \"",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
|
@ -590,7 +599,10 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
Some(Err(LexError::syntax_error(
|
Some(Err(LexError::syntax_error(
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!("no such operator: <.", "<.という演算子はありません"),
|
switch_lang!(
|
||||||
|
"japanese" => "<.という演算子はありません",
|
||||||
|
"english" => "no such operator: <.",
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -764,8 +776,17 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
Some(Err(LexError::syntax_error(
|
Some(Err(LexError::syntax_error(
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!("cannot use a tab as a space", "タブ文字は使用できません"),
|
switch_lang!(
|
||||||
Some(switch_lang!("use spaces", "スペースを使用してください").into()),
|
"japanese" => "タブ文字は使用できません",
|
||||||
|
"english" => "cannot use a tab as a space",
|
||||||
|
),
|
||||||
|
Some(
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "スペース( )を使用してください",
|
||||||
|
"english" => "use spaces ( )",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -788,8 +809,8 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("`{}` cannot be defined by user", &token.content),
|
"japanese" => format!("`{}`はユーザー定義できません", &token.content),
|
||||||
format!("`{}`はユーザー定義できません", &token.content)
|
"english" => format!("`{}` cannot be defined by user", &token.content),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)));
|
)));
|
||||||
|
@ -802,8 +823,8 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("back quotes (`) not closed"),
|
"japanese" => format!("バッククォート(`)が閉じられていません"),
|
||||||
format!("バッククォート(`)が閉じられていません")
|
"english" => format!("back quotes (`) not closed"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
|
@ -819,8 +840,8 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
0,
|
0,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
format!("invalid character: '{invalid}'"),
|
"japanese" => format!("この文字は使用できません: '{invalid}'"),
|
||||||
format!("この文字は使用できません: '{invalid}'")
|
"english" => format!("invalid character: '{invalid}'"),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
|
|
|
@ -439,7 +439,10 @@ impl Parser {
|
||||||
let err = ParseError::syntax_error(
|
let err = ParseError::syntax_error(
|
||||||
0,
|
0,
|
||||||
loc,
|
loc,
|
||||||
switch_lang!("failed to parse a block", "ブロックの解析に失敗しました"),
|
switch_lang!(
|
||||||
|
"japanese" => "ブロックの解析に失敗しました",
|
||||||
|
"english" => "failed to parse a block",
|
||||||
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -496,8 +499,8 @@ impl Parser {
|
||||||
0,
|
0,
|
||||||
self.peek().unwrap().loc(),
|
self.peek().unwrap().loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"Cannot use type bounds in a declaration of a variable",
|
"japanese" => "変数宣言で型制約は使えません",
|
||||||
"変数宣言で型制約は使えません"
|
"english" => "Cannot use type bounds in a declaration of a variable",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -509,16 +512,6 @@ impl Parser {
|
||||||
self.skip();
|
self.skip();
|
||||||
Some(self.try_reduce_type_spec()?)
|
Some(self.try_reduce_type_spec()?)
|
||||||
} else {
|
} else {
|
||||||
if self.cur_is(Colon) {
|
|
||||||
self.warns.push(ParseError::syntax_warning(0, name.loc(), switch_lang!(
|
|
||||||
"Since it is obvious that the variable is of type `Type`, there is no need to specify the type.",
|
|
||||||
"変数がType型であることは明らかなので、型指定は不要です。"
|
|
||||||
), Some(switch_lang!(
|
|
||||||
"Are you sure you're not confusing it with subclass declaration (<:)?",
|
|
||||||
"サブクラスの宣言(<:)ではありませんか?"
|
|
||||||
).into())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else if self.cur_is(Colon) {
|
} else if self.cur_is(Colon) {
|
||||||
|
@ -663,8 +656,8 @@ impl Parser {
|
||||||
0,
|
0,
|
||||||
t.loc(),
|
t.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"Binary operators cannot be used in left-values",
|
"japanese" => "左辺値の中で中置演算子は使えません",
|
||||||
"左辺値の中で中置演算子は使えません"
|
"english" => "Binary operators cannot be used in left-values",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -754,9 +747,10 @@ impl Parser {
|
||||||
return Err(ParseError::syntax_error(
|
return Err(ParseError::syntax_error(
|
||||||
0,
|
0,
|
||||||
param.loc(),
|
param.loc(),
|
||||||
|
// TODO: switch_lang!
|
||||||
"non-default argument follows default argument",
|
"non-default argument follows default argument",
|
||||||
None,
|
None,
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
(false, false) => {
|
(false, false) => {
|
||||||
non_default_params.push(param);
|
non_default_params.push(param);
|
||||||
|
@ -768,8 +762,8 @@ impl Parser {
|
||||||
0,
|
0,
|
||||||
t.loc(),
|
t.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"Binary operators cannot be used in parameters",
|
"japanese" => "仮引数の中で中置演算子は使えません",
|
||||||
"仮引数の中で中置演算子は使えません"
|
"english" => "Binary operators cannot be used in parameters",
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1021,12 +1015,15 @@ impl Parser {
|
||||||
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
||||||
}
|
}
|
||||||
// TODO: App, Array, Record, BinOp, UnaryOp,
|
// TODO: App, Array, Record, BinOp, UnaryOp,
|
||||||
other => {
|
other => Err(ParseError::syntax_error(
|
||||||
Err(ParseError::syntax_error(0, other.loc(), switch_lang!(
|
0,
|
||||||
"this expression is not computable at the compile-time, so cannot used as a type-argument",
|
other.loc(),
|
||||||
"この式はコンパイル時計算できないため、型引数には使用できません",
|
switch_lang!(
|
||||||
), None))
|
"japanese" => "この式はコンパイル時計算できないため、型引数には使用できません",
|
||||||
}
|
"english" => "this expression is not computable at the compile-time, so cannot used as a type-argument",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
59
doc/EN/dev_guide/i18n_messages.md
Normal file
59
doc/EN/dev_guide/i18n_messages.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# Multilingualization of Messages
|
||||||
|
|
||||||
|
Erg is working on making all messages (start, option, doc, hint, warning, error messages, etc.) multilingual within the language.
|
||||||
|
This project is open to anyone without detailed knowledge of Rust or Erg. Your participation is always welcome.
|
||||||
|
|
||||||
|
Here is how to translate them.
|
||||||
|
|
||||||
|
## Search `switch_lang!`
|
||||||
|
|
||||||
|
In the Erg source code, look for the item `switch_lang!` (use grep or your editor's search function).
|
||||||
|
You should find something like this:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
This message is currently supported only in Japanese and English. Let's add a simplified Chinese message as a test.
|
||||||
|
|
||||||
|
## Add a New Message
|
||||||
|
|
||||||
|
Add translated messages as you see the content in other languages. Don't forget the comma (`,`) last.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
|
"simplified_chinese" => format!("该功能({name})还没有正式提供"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that English is the default and must come last.
|
||||||
|
The `{name}` part is a Rust formatting feature that allows you to embed the contents of a variable (`name`) into a string.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Now, let's build with the `--features simplified_chinese` option.
|
||||||
|
|
||||||
|
<img src="../../../assets/screenshot_i18n_messages.png" alt='screenshot_i18n_messages'>
|
||||||
|
|
||||||
|
We did it!
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
Q: What does a specification like `{RED}{foo}{RESET}` mean?
|
||||||
|
A: {RED} and subsequent letters will be displayed in red. {RESET} will restore the color.
|
||||||
|
|
||||||
|
Q: If I want to add my language, how do I replace the `"simplified_chinese" =>` part?
|
||||||
|
|
||||||
|
The following languages are currently supported:
|
||||||
|
|
||||||
|
* "english" (default)
|
||||||
|
* "japanese"
|
||||||
|
* "simplified_chinese"
|
||||||
|
* "traditional_chinese"
|
||||||
|
|
||||||
|
If you would like to add languages other than these, please make a request.
|
58
doc/JA/dev_guide/i18n_messages.md
Normal file
58
doc/JA/dev_guide/i18n_messages.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# Multilingualization of Messages
|
||||||
|
|
||||||
|
Ergはメッセージ(スタート、オプション、ドキュメント、ヒント、警告、エラーメッセージなど)の多言語化を進めています。
|
||||||
|
このプロジェクトは、RustやErgの詳しい知識がなくても参加することができます。ぜひ協力をお願いします。
|
||||||
|
|
||||||
|
以下に、多言語化の方法を説明します。
|
||||||
|
|
||||||
|
## `switch_lang!`を探す
|
||||||
|
|
||||||
|
Ergのソースコードの中で、`switch_lang!`という項目を探します(grepやエディタの検索機能を使ってください)。
|
||||||
|
以下のようなものが見つかるはずです。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
このメッセージは現在、日本語と英語のみでサポートされています。試しに簡体字のメッセージを追加してみましょう。
|
||||||
|
|
||||||
|
## メッセージを追加する
|
||||||
|
|
||||||
|
他の言語の内容を見ながら、翻訳されたメッセージを追加してください。最後にカンマ(`,`)を忘れないでください。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("この機能({name})はまだ正式に提供されていません"),
|
||||||
|
"simplified_chinese" => format!("该功能({name})还没有正式提供"),
|
||||||
|
"english" => format!("this feature({name}) is not implemented yet"),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
なお、英語はデフォルトであり、必ず最後に来るようにします。
|
||||||
|
`{name}` の部分は Rust のフォーマット機能で、変数の内容 (`name`) を文字列に埋め込むことができます。
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
では、`--features simplified_chinese` オプションを付けてビルドしてみましょう。
|
||||||
|
|
||||||
|
<img src="../../../assets/screenshot_i18n_messages.png" alt='screenshot_i18n_messages'>
|
||||||
|
|
||||||
|
やりましたね!
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
Q: `{RED}{foo}{RESET}` のような指定は何を意味するのでしょうか?
|
||||||
|
A: {RED}以降が赤色で表示されます。{RESET}で色を元に戻します。
|
||||||
|
|
||||||
|
Q: 自分の言語を追加したい場合、`"simplified_chinese" =>`の部分はどのように置き換えればよいですか?
|
||||||
|
A: 現在、以下の言語がサポートされています。
|
||||||
|
|
||||||
|
* "english" (デフォルト)
|
||||||
|
* "japanese" (日本語)
|
||||||
|
* "simplified_chinese" (簡体字中国語)
|
||||||
|
* "traditional_chinese"(繁体字中国語)
|
||||||
|
|
||||||
|
これら以外の言語を追加したい場合は、リクエストしてください。
|
Loading…
Add table
Add a link
Reference in a new issue