Compare commits

..

No commits in common. "main" and "v1.1.0" have entirely different histories.
main ... v1.1.0

17 changed files with 64 additions and 217 deletions

26
.github/README.md vendored
View File

@ -38,20 +38,26 @@ To use localizer-rs, you need a directory (eg. `translations`) with your transla
1. Import the localizer-rs crate: 1. Import the localizer-rs crate:
```rust,ignore ```rust
use localizer_rs; use localizer_rs;
``` ```
2. Create a new config object: 2. Create a new config object:
```rust,ignore ```rust
let config = localizer_rs::Config::new("translations", "en");
let config = localizer_rs::Config::new("DIRECTORY NAME", "LANGUAGE NAME");
``` ```
3. Translate your text: 3. Translate your text:
```rust,ignore ```rust
localizer_rs::t!(config, "key", "placeholder" ="value");
config.t("key", vec!["placeholder", "value"]);
``` ```
## Example ## Example
@ -59,27 +65,33 @@ To use localizer-rs, you need a directory (eg. `translations`) with your transla
With the following `en.json` file. With the following `en.json` file.
```json ```json
{ {
"error": "{{color.red}}{{bold}}Error:{{end}} Something went wrong: {{details}}." "error": "{{color.red}}{{bold}}Error:{{end}} Something went wrong: {{details}}."
} }
``` ```
And the following rust code. And the following rust code.
```rust,ignore ```rust
use localizer_rs; use localizer_rs;
fn main() { fn main() {
let config: localizer_rs::Config = localizer_rs::Config::new("translations", "en"); let config: localizer_rs::Config = localizer_rs::Config::new("translations", "en");
println!("{:}", localizer_rs::t!(config, "error", "details" = "Path not found")); println!("{:}", config.t("error", vec![("details", "Path not found")]));
} }
``` ```
You will get the following output: You will get the following output:
```bash ```bash
Error: Something went wrong: Path not found. Error: Something went wrong: Path not found.
``` ```
Where `Error:` is red and bold. Where `Error:` is red and bold.

2
.github/SECURITY.md vendored
View File

@ -6,8 +6,6 @@
| -------- | ------------------ | | -------- | ------------------ |
| `v1.0.0` | :white_check_mark: | | `v1.0.0` | :white_check_mark: |
| `v1.1.0` | :white_check_mark: | | `v1.1.0` | :white_check_mark: |
| `v1.1.1` | :white_check_mark: |
| `v1.2.0` | :white_check_mark: |
## Reporting a Vulnerability ## Reporting a Vulnerability

3
.github/errors.md vendored
View File

@ -1,3 +0,0 @@
# errors module
Module for dealing with errors.

View File

@ -1,14 +0,0 @@
name: Codecov
permissions: read-all
on:
[push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@ -16,9 +16,9 @@ jobs:
matrix: matrix:
python-version: ["3.8"] python-version: ["3.8"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dependencies from txt files - name: Install dependencies from txt files
@ -28,7 +28,7 @@ jobs:
install-rust-dependencies: install-rust-dependencies:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install dependencies from Cargo.toml - name: Install dependencies from Cargo.toml
run: cargo update run: cargo update
- name: Install dev-dependencies from Cargo.toml - name: Install dev-dependencies from Cargo.toml
@ -39,8 +39,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v4 uses: actions/checkout@v3
if: ${{ github.event_name != 'push' }} if: ${{ github.event_name != 'push' }}
- name: Dependency Review - name: Dependency Review
if: ${{ github.event_name != 'push' }} if: ${{ github.event_name != 'push' }}
uses: actions/dependency-review-action@v4 uses: actions/dependency-review-action@v3

View File

@ -20,6 +20,6 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/labeler@v5 - uses: actions/labeler@v4
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@ -26,7 +26,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
fetch-depth: 0 fetch-depth: 0

View File

@ -11,7 +11,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Build - name: Build
run: cargo build --verbose run: cargo build --verbose
- name: Run tests - name: Run tests

View File

@ -1,7 +1,7 @@
[package] [package]
name = "localizer-rs" name = "localizer-rs"
description = "Localizer helps localize (translate) your rust applications using json files." description = "Localizer helps localize (translate) your rust applications using json files."
version = "1.2.0" version = "1.1.0"
authors = [ authors = [
"ElBe-Plaq <elbe.dev.plaq@gmail.com>" "ElBe-Plaq <elbe.dev.plaq@gmail.com>"
] ]
@ -10,7 +10,7 @@ rust-version = "1.69"
documentation = "https://docs.rs/localizer_rs/" documentation = "https://docs.rs/localizer_rs/"
readme = ".github/README.md" readme = ".github/README.md"
repository = "https://github.com/ElBe-Development/localizer-rs/" repository = "https://github.com/ElBe-Development/localizer-rs/"
license = "MIT" license-file = "LICENSE.txt"
keywords = ["i18n", "L10n", "json", "local", "translation"] keywords = ["i18n", "L10n", "json", "local", "translation"]
categories = [ categories = [
"internationalization", "internationalization",
@ -20,4 +20,4 @@ publish = true
[dependencies] [dependencies]
serde = "1.0.188" serde = "1.0.188"
serde_json = "1.0.107" serde_json = "1.0.106"

View File

@ -1,10 +0,0 @@
coverage:
status:
project:
default:
target: 50%
threshold: 1%
comment:
require_changes: true
require_ci_to_pass: false

View File

@ -1 +1 @@
pre-commit==4.1.0; python_version>='3.8' pre-commit==3.3.2; python_version>='3.8'

View File

@ -5,16 +5,15 @@ fn main() {
println!( println!(
"{:}", "{:}",
localizer_rs::t!( config.t(
config,
"error", "error",
"details" = "Something went wrong when trying to do stuff" vec![("details", "Something went wrong when trying to do stuff")]
) )
); );
println!( println!(
"{:}", "{:}",
localizer_rs::t!(config, "success", "balance" = "$10", "user" = "John Doe") config.t("success", vec![("balance", "$10"), ("user", "John Doe")])
); );
println!("{:}", localizer_rs::t!(config, "all")); println!("{:}", config.t("all", vec![]));
} }

View File

@ -10,7 +10,8 @@ build *ARGUMENTS:
# Removes temporary files # Removes temporary files
clean: clean:
cargo clean rm -rf target
rm -rf Tools/__pycache__
# Lints the rust source files # Lints the rust source files
lint *ARGUMENTS: lint *ARGUMENTS:

View File

@ -1,6 +1,5 @@
#![doc = include_str!("../.github/errors.md")]
// localizer-rs errors // localizer-rs errors
// Version: 1.1.1 // Version: 1.1.0
// Copyright (c) 2023-present ElBe Development. // Copyright (c) 2023-present ElBe Development.
@ -59,39 +58,12 @@ use std::fmt;
/// ``` /// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Error { pub struct Error {
/// The errors name.
pub name: String, pub name: String,
/// The error description.
pub description: String, pub description: String,
/// The errors exit code.
pub exit_code: i32, pub exit_code: i32,
} }
/// Display implementation for the error object.
impl fmt::Display for Error { impl fmt::Display for Error {
/// Format implementation for the error object.
///
/// # Parameters
///
/// - `self`: The error object.
/// - `f`: The [`fmt::Formatter`] to use.
///
/// # Returns
///
/// A [`fmt::Result`] containing the formatted error message.
///
/// # Examples
///
/// ```rust
/// # use localizer_rs;
/// # let error = localizer_rs::errors::Error::new("name", "description", 1);
/// println!("{}", error);
/// ```
///
/// # See also
///
/// - [`fmt::Display`]
/// - [`Error`]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\x1b[31;1m{}\x1b[0m: {}", self.name, self.description) write!(f, "\x1b[31;1m{}\x1b[0m: {}", self.name, self.description)
} }

View File

@ -1,6 +1,6 @@
#![doc = include_str!("../.github/README.md")] #![doc = ".github/README.md"]
// localizer-rs // localizer-rs
// Version: 1.2.0 // Version: 1.1.0
// Copyright (c) 2023-present ElBe Development. // Copyright (c) 2023-present ElBe Development.
@ -37,6 +37,8 @@ use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use errors as error_lib;
use serde_json; use serde_json;
@ -50,8 +52,7 @@ use serde_json;
/// ///
/// # Parameters /// # Parameters
/// ///
/// - `path`: The directory containing the translation files. /// - `path`: The directory containing the translation files. The directory is relative to the path the executable was executed from.
/// The directory is relative to the path the executable was executed from.
/// - `language`: The language to translate to. /// - `language`: The language to translate to.
/// ///
/// # Returns /// # Returns
@ -69,10 +70,7 @@ use serde_json;
/// ``` /// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Config { pub struct Config {
/// The directory containing the translation files. The directory is relative to the path the
/// executable was executed from.
pub path: String, pub path: String,
/// The language to translate to.
pub language: String, pub language: String,
} }
@ -86,8 +84,7 @@ impl Config {
/// ///
/// # Parameters /// # Parameters
/// ///
/// - `path`: The directory containing the translation files. /// - `path`: The directory containing the translation files. The directory is relative to the path the executable was executed from.
/// The directory is relative to the path the executable was executed from.
/// - `language`: The language to translate to. /// - `language`: The language to translate to.
/// ///
/// # Returns /// # Returns
@ -125,8 +122,7 @@ impl Config {
/// # Parameters /// # Parameters
/// ///
/// - `self`: The config object. This must be mutable. /// - `self`: The config object. This must be mutable.
/// - `str_path`: The directory containing the translation files. /// - `str_path`: The directory containing the translation files. The directory is relative to the path the executable was executed from.
/// The directory is relative to the path the executable was executed from.
/// ///
/// # Returns /// # Returns
/// ///
@ -153,13 +149,14 @@ impl Config {
match path.try_exists() { match path.try_exists() {
Ok(value) => { Ok(value) => {
if !value { if !value {
let error: errors::Error = let error: error_lib::Error =
errors::Error::new("OS Error", "Translation path was not found", 1); error_lib::Error::new("OS Error", "Translation path was not found", 1);
error.raise(format!("Path: {:?}", str_path).as_str()); error.raise(format!("Path: {:?}", str_path).as_str());
} }
} }
Err(_error) => { Err(_error) => {
let error: errors::Error = errors::Error::new("OS Error", "Could not open path", 2); let error: error_lib::Error =
error_lib::Error::new("OS Error", "Could not open path", 2);
error.raise(format!("Path: {:?}\nDetails: {}", str_path, _error).as_str()); error.raise(format!("Path: {:?}\nDetails: {}", str_path, _error).as_str());
} }
} }
@ -167,8 +164,8 @@ impl Config {
self.path = String::from(match path.to_owned().to_str() { self.path = String::from(match path.to_owned().to_str() {
Some(value) => value, Some(value) => value,
None => { None => {
let error: errors::Error = let error: error_lib::Error =
errors::Error::new("OS Error", "Path does not seem to be valid", 3); error_lib::Error::new("OS Error", "Path does not seem to be valid", 3);
error.raise(format!("Path: {:?}", str_path).as_str()); error.raise(format!("Path: {:?}", str_path).as_str());
"" ""
} }
@ -225,49 +222,15 @@ impl Config {
/// ///
/// # See also /// # See also
/// ///
/// - [`t!()`]
/// - [`Config`] /// - [`Config`]
pub fn t(&self, key: &str, arguments: Vec<(&str, &str)>) -> String { pub fn t(&self, key: &str, arguments: Vec<(&str, &str)>) -> String {
return self.translate(key, arguments); return self.translate::<serde_json::Value>(key, arguments);
} }
/// Translates the specified key in the language specified in the config. fn translate<T>(&self, key: &str, mut arguments: Vec<(&str, &str)>) -> String
/// where
/// # Parameters T: serde::Serialize + for<'de> serde::Deserialize<'de>,
/// {
/// - `self`: The config object.
/// - `key`: The key to translate to.
/// - `arguments`: The arguments to replace.
///
/// # Returns
///
/// A `String` containing the translated value.
///
/// # Raises
///
/// This method throws an exception and exits if
///
/// - The translation file could not be found
/// - The translation file could not be opened
/// - The translation file could not be parsed
/// - The parsed json could not be converted to a json value
/// - The converted json could not be indexed
///
/// # Examples
///
/// ```rust
/// # use localizer_rs;
/// # let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en");
/// config.translate("test", vec![]);
/// ```
///
/// # See also
///
/// - [`t!()`]
/// - [`Config`]
/// - [`Config::t()`]
/// - [`serde_json`]
pub fn translate(&self, key: &str, mut arguments: Vec<(&str, &str)>) -> String {
let mut colors: Vec<(&str, &str)> = vec![ let mut colors: Vec<(&str, &str)> = vec![
// Formatting codes // Formatting codes
("end", "\x1b[0m"), ("end", "\x1b[0m"),
@ -338,8 +301,8 @@ impl Config {
}; };
let reader: BufReader<File> = BufReader::new(file); let reader: BufReader<File> = BufReader::new(file);
let json: serde_json::Value = match serde_json::to_value::<serde_json::Value>( let json: serde_json::Value = match serde_json::to_value::<T>(
match serde_json::from_reader::<BufReader<File>, serde_json::Value>(reader) { match serde_json::from_reader::<BufReader<File>, T>(reader) {
Ok(value) => value, Ok(value) => value,
Err(_error) => { Err(_error) => {
let error: errors::Error = errors::Error::new( let error: errors::Error = errors::Error::new(
@ -399,50 +362,3 @@ impl Config {
return result; return result;
} }
} }
/// Translates the specified key in the language specified in the config.
///
/// # Parameters
///
/// - `config`: The config object.
/// - `key`: The key to translate to.
/// - `arguments`: Optional parameter. The arguments to replace. Has to be of type `"name" = "value"`.
///
/// # Returns
///
/// A `String` containing the translated value.
///
/// # Examples
///
/// ```rust
/// # use localizer_rs;
/// # let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en");
/// localizer_rs::t!(config, "test");
/// localizer_rs::t!(config, "test", "variable" = "content");
/// ```
///
/// # See also
///
/// - [`Config`]
/// - [`Config::t()`]
#[macro_export]
macro_rules! t {
($config:expr, $key:expr) => {
{
$config.t($key, vec![])
}
};
($config:expr, $key:expr, $($argument_name:literal = $argument_value:literal),* $(,)?) => {
{
let mut arguments: Vec<(&str, &str)> = vec![];
$(
arguments.push(($argument_name, $argument_value));
)*
$config.t($key, arguments)
}
};
}

View File

@ -1,5 +1,5 @@
// localizer-rs error tests // localizer-rs error tests
// Version: 1.1.1 // Version: 1.1.0
// Copyright (c) 2023-present ElBe Development. // Copyright (c) 2023-present ElBe Development.

View File

@ -1,5 +1,5 @@
// localizer-rs tests // localizer-rs tests
// Version: 1.2.0 // Version: 1.1.0
// Copyright (c) 2023-present ElBe Development. // Copyright (c) 2023-present ElBe Development.
@ -80,18 +80,6 @@ mod tests {
#[test] #[test]
fn test_translate() { fn test_translate() {
let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en");
let translation: String =
config.translate("error", vec![("details", "Something went wrong")]);
assert_eq!(
translation.as_str(),
"\x1b[31m\x1b[1mError:\x1b[0m Something went wrong"
);
}
#[test]
fn test_translate_t() {
let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en"); let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en");
let translation: String = config.t("error", vec![("details", "Something went wrong")]); let translation: String = config.t("error", vec![("details", "Something went wrong")]);
@ -100,16 +88,4 @@ mod tests {
"\x1b[31m\x1b[1mError:\x1b[0m Something went wrong" "\x1b[31m\x1b[1mError:\x1b[0m Something went wrong"
); );
} }
#[test]
fn test_translate_macro() {
let config: localizer_rs::Config = localizer_rs::Config::new("examples/translations", "en");
let translation: String =
localizer_rs::t!(config, "error", "details" = "Something went wrong");
assert_eq!(
translation.as_str(),
"\x1b[31m\x1b[1mError:\x1b[0m Something went wrong"
);
}
} }