Code Monkey home page Code Monkey logo

i18n4k's People

Contributors

aftabahmadtw avatar comahe-de avatar jan222ik avatar shabinder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

i18n4k's Issues

Locale not set for Javascript code in test

I have a use case where I am trying to generate a JS library and JVM library from the same common code. I'm currently writing a test for my javascript code as follows:
commonMain

class Example {
    fun build(locale: String): String {
        updateLocale(locale)
        return Messages.hello("Trent");
    }
}

internal expect fun updateLocale(locale: String)

expect object TestFactory {
    fun createExample(): Example
}

jsMain

actual object TestFactory {
    actual fun createExample(): Example {
        val i18n4kConfig = I18n4kConfigImmutable()
        i18n4k = i18n4kConfig;

        var localeCount = 0;
        Messages.registerTranslationFactory(MessagesProviderFactoryViaFetch(
            pathToResource="/Messages_es_ES.i18n4k.txt",
            onLoaded={ localeCount = Messages.locales.size }
        ))

        return Example()
    }
}

internal actual fun updateLocale(locale: String) {
    val i18n4kConfig = I18n4kConfigImmutable();
    i18n4k = i18n4kConfig
    var localeSplit = locale.split("_").toTypedArray()
    i18n4kConfig.withLocale(Locale(localeSplit[0], localeSplit[1]))
}

Currently, my Java implementation works with MessageProviderViaResource. I'm able to return the correct message. For the JS test though, it seems as if the locale or translation files are not being loaded correctly, as I get an error Expected <Hola, Trent!>, actual <?0?>.

My test code is as follows:

class SampleTest {
    @Test
    fun testCreateExample() {
        val ex  = TestFactory.createExample()
        val s = ex.build("es_ES")
        assertEquals("Hola, Trent!", s)
    }
}

It seems that the issue might be with MessagesProviderFactoryViaFetch as I'm running via a browser test. The goal of this sample project is to provide a proof of concept for a JS library that will be used client and server side in a NodeJS application.

I am extrapolating from the JS example since my use case does not require React, but I think I am on the right path. Any help is appreciated!

Question: locale changing for jvm source set

Hello @comahe-de !
I'm looking for i18n library for Kotlin Multiplatform and I have jvm and js source set only(Ktor and React).
My question is about locale changing - it's totally clear that changing locale atomic ref in I18n4kConfig is ok for the frontend(js or mobile app) as you have separate application instance per client, but what about backend? You have only one backend instance for many clients and each client can have different locale.
For example we have 2 clients with different locale(client_1 - en, client_2 - de). Each client makes many parallel http requests with different locale. Each request contains many steps for generation some localized text documents, and the response time can be, for example, from 500ms to 20sec.
That's means that for each request I will change locale atomic ref in I18n4kConfig and it could happen that client_1 request is not finished yet, but client_2 request is already begun. What would happen in this case? Would client_1 receive part of the response in en and part in de?

Issue in generating code

I have faced an issue in SpotiFlyer project. Some strings without parameters are detected as parameterized strings.

For example, for "What Went Wrong...", the generated code must be getLocalizedStringFactory0, but it is getLocalizedStringFactory1.

The problem is solved by passing an empty string.

Problems:

  /**
   * Copy to Clipboard
   */
  @JvmStatic
  public val copyToClipboard: LocalizedStringFactory1 = getLocalizedStringFactory1(15)

  /**
   * Copy Paste Below Code while creating Github Issue / Reporting this issue for better help.
   */
  @JvmStatic
  public val copyCodeInGithubIssue: LocalizedStringFactory1 = getLocalizedStringFactory1(14)

  /**
   * What Went Wrong...
   */
  @JvmStatic
  public val whatWentWrong: LocalizedStringFactory1 = getLocalizedStringFactory1(83)

Versions:

  • kotlinVersion = "1.5.10"
  • i18n4kVersion="0.1.2"
  • Android Studio="Android Studio Arctic Fox | 2020.3.1"

Generated code: https://justpaste.it/1wu1i

Ability to add some additional parameters to the message text like gender.

In many language like Polish, Czech or Spanish, we distinguish between gender forms.
User in Spanish can be usuario (if male) or usuaria (if female), in Polish it is użytkownik, użytkowniczka.
For example if I want to print message for my user: "You got mail! from user Greta" this would look different in Polish depending on my users gender and Gretas gender. "You got" whould be translated to Dostałaś when female, or Dostałeś when male. As i said before user would be użytkowniczki or użytkownika for female or male. So if both are females this message in polish should be "Dostałaś maila od użytkowniczki Grety". You can see that also Gretas name have different forms (it is declension or polish deklinacja) and depends on the situation in the sentence. If user sends mail to Greta, i want to print "You sent mail to Greta" now it is "Wysłałaś maila do Grety" when Wysłałaś is female form of "you sent" and again you can see different form of Greta declension.
So the problem is how to prepare the translation document MyMessages_en.properties and MyMessages_pl.properties, so that i don't have to manage these forms in my code (because it should be as simple as MyMessage.sayHello("word", gender = Gender.FEMALE)). Managing these forms in code would be nightmare especially if you are not linguistic expert in all languages. Yet natives can translate these sentences and spot the pattern intuitively.

I can see that this is complicated and I am not sure if I have clarified it. But form my perspective the solution whould be as follows.
Now programmers can create string like:
youGotMail=You got mail from user {0}
but if i whould like to customize it for the user in polish these should be like:
youGotMail={0} maila od {1} {2}
and manage this in code the 0 - male or female form of you got, 1 - user (male/female), 2 - Greta as specific declension form (here polish Dopełniacz).
So the translator should instead specify something like this:

youGotMail={youGot} maila od {user} {username.DOP}
youGotMail.youGot.FEMALE=dostałaś
youGotMail.youGot.MALE=dostałeś
youGotMail.user.FEMALE=użytkowniczki
youGotMail.user.MALE=użytkownika

The username.DOP then should have somewhere a dictionary (maby provided by translator) with all words that can be used by software, so that the programmer only specify the word, and then the correct form (here dopełniacz) is automaticaly applied.
The programmer whould then just provide required information about the word (IDE whould check required forms) like gender and specify the name (of Greta) and then i18n4k whould pick preferable form for the words.

The customizing of localed messages can be passed from programmes to the translators. Programmer should only specify some basic information about the word (passed as variable), like gender.
This greatly increases the user experience and i think it will become more widespread with android 14.

I just think this whould be fantastic feature, but maby I'm wrong and it's just overcomplicated and unnecesary.

Issue with setting country specific locale for translations that are generated as source code

I'm working off the 0.7.0-SNAPSHOT version on main. I've noticed that the locale objects do not get built correctly for any locale that is not registered at runtime but included as a sourceCodeLocale.

My steps are that I've defined the properties files and included the following in my build.gradle:

    i18n4k {
        sourceCodeLocales = listOf("en_US", "es_ES")
    }

The generated object is built and the resulting .locales call returns locales that have not been parsed out like they are if they are registered at runtime.

Screenshot 2023-10-31 at 2 35 09 PM

Arabic shows up as ?????

Column {
            Text(Strings.homeScreen(localization.locale))
            Box(Modifier.height(Dp(12.0f))){}
            Text("العربية")
        }

2023-06-30_00-08

Issues in latest release 0.4.0

The new targets were added here: 89ace5d but don't seem to be published in the new version: https://search.maven.org/search?q=de.comahe.i18n4k

I also seem to get an error when trying to build the new version:

An exception occurred applying plugin request [id: 'de.comahe.i18n4k', version: '0.4.0']
> Failed to apply plugin 'de.comahe.i18n4k'.
   > Could not create an instance of type de.comahe.i18n4k.gradle.plugin.I18n4kExtension.
      > Could not generate a decorated class for type I18n4kExtension.
         > de/comahe/i18n4k/messages/formatter/MessageFormatter

The i18n4k gradle plugin adds duplicate folders to your SourceSets

See https://github.com/comahe-de/i18n4k/blob/master/i18n4k-gradle-plugin/src/main/kotlin/de/comahe/i18n4k/gradle/plugin/I18n4kPlugin.kt#L159-L163

It grabs a copy of all the existing source folders, adds the new one, and then calls srcDirs which adds all the directories to the source set. This creates a list that looks like:

src/main/resources
src/main/resources
build/generated/resources/i18n4k

Unfortunately it's a bit hard to see that this is happening since a lot of the gradle APIs use Sets and the duplicates often get filtered out, but when the processResources task runs, it definitely ends up trying to copy all your resources twice, leading to build errors (or a ton of warnings if you set duplicatesStrategy = DuplicatesStrategy.WARN).

A simple workaround is either to set duplicatesStrategy and accept that your build will print a bunch of warnings, or to add this to your processResources task (Kotlin DSL syntax):

tasks.processResources {
    doFirst {
        val s = sourceSets.main.get().resources
        s.setSrcDirs(s.srcDirs)
    }
}

s.srcDirs returns a Set of files so it removes the duplicates for you.

Encoding problem on Linux (Ubuntu)

I have create properties file. It stored as UTF-8:
(Contains cyrilic content)

google_login=Зайти з Google
logout=Вийти

However the generated kt file has a strange content:

private object Str_uk : MessagesProvider {
  private val _data: Array<String?> = arrayOf(
      "Ð\u0097айÑ\u0082и з Google",
      "Ð\u0092ийÑ\u0082и")

  public override val locale: Locale = Locale("uk")

  public override val size: Int = _data.size

  public override fun `get`(index: Int): String? = _data[index]
}

Strings with '%' in them cause the build to fail

Putting a % character in a string causes the build to fail with this exception:

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':generateI18n4kFiles'.
....
Caused by: java.lang.IllegalArgumentException: index 1 for '% ' not in range (received 0 arguments)
	at com.squareup.kotlinpoet.CodeBlock$Builder.add(CodeBlock.kt:312)
	at com.squareup.kotlinpoet.Documentable$Builder.addKdoc(Documentable.kt:27)
	at com.squareup.kotlinpoet.PropertySpec$Builder.addKdoc(PropertySpec.kt:278)
	at de.comahe.i18n4k.generator.I18n4kGenerator.generateMessagesObject(I18n4kGenerator.kt:188)
	at de.comahe.i18n4k.generator.I18n4kGenerator.generateSourceCode(I18n4kGenerator.kt:137)
	at de.comahe.i18n4k.generator.I18n4kGenerator.run(I18n4kGenerator.kt:115)
	at de.comahe.i18n4k.generator.I18n4kProcessor.execute(I18n4kProcessor.kt:68)
	....

It's coming from the kotlinpoet library which has some specific syntax it looks for:
https://github.com/square/kotlinpoet/blob/main/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt#L32-L59

I don't think there's any need for i18n4k to use these placeholder sequences, so maybe all text passed into the PropertSpec should replace all % characters with %%?

Issue with longer text.

Hello,
first at all thanks for this library it really helped me to solve multilanguage feature in my kotlin/js react web application.
I found out there is an issue with the longer text. If you have longer text in properties file it won't generate the translation .kt file correctly that results into build error.

property file:
longTextExample=Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus faucibus molestie nisl. Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis velit mauris vel metus. Pellentesque ipsum. Integer malesuada. Fusce wisi. Nullam dapibus fermentum ipsum. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Quisque tincidunt scelerisque libero. Etiam posuere lacus quis dolor. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Pellentesque sapien.

iIt will generate string in translation .kt file:
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus faucibus molestie nisl.
Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis
velit mauris vel metus. Pellentesque ipsum. Integer malesuada. Fusce wisi. Nullam dapibus
fermentum ipsum. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Integer rutrum, orci vestibulum ullamcorper ultricies,
lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Quisque tincidunt
scelerisque libero. Etiam posuere lacus quis dolor. In laoreet, magna id viverra
tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Neque porro
quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia
non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat
voluptatem. Pellentesque sapien.",

expected result:
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus faucibus molestie nisl."
+ "Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis"
+ "velit mauris vel metus. Pellentesque ipsum. Integer malesuada. Fusce wisi. Nullam dapibus"
+ "fermentum ipsum. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi"
+ "ut aliquip ex ea commodo consequat. Integer rutrum, orci vestibulum ullamcorper ultricies,"
+ "lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Quisque tincidunt"
+ "scelerisque libero. Etiam posuere lacus quis dolor. In laoreet, magna id viverra"
+ "tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Neque porro"
+ "quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia"
+ "non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat"
+ "voluptatem. Pellentesque sapien.",

i18n4k is causing issues when used with projects that use KSP / eager evaluation methods should be replaced with lazy evaluation methods

I'm the author of a project called Kobweb, which uses KSP. One of my users reported a callstack that came from this plugin.

image

with this error:

* What went wrong:
A problem occurred configuring project ':site'.
> Could not create task ':site:kobwebExport'.
   > Task with name 'kspKotlinJs' not found in project ':site'.

They said they saw a similar error when using ktorfit with your plugin, and that is another project that uses ksp.

After some investigation, we think this line is the culprit, forcing eager evaluation before other plugins are ready :

https://github.com/comahe-de/i18n4k/blob/c8516196097279dd58411c2b7b34c703dfddb1a6/i18n4k-gradle-plugin/src/main/kotlin/de/comahe/i18n4k/gradle/plugin/I18n4kPlugin.kt#L121C20-L121C20

It should probably be rewritten as

project.tasks.matching { it.name.startsWith("compile") }.configureEach {
   it.dependsOn(GENERATE_I18N_SOURCES_TASK_NAME)
}

You should probably also change the withType.forEach calls to withType.configureEach and the findByName calls also to use matching.

I'm not a Gradle expert, nor am I sure if you fix this it will fix the issues I'm seeing with the error linked above, but making these changes are, to my understanding, modern Gradle best practices. See also: https://docs.gradle.org/current/userguide/task_configuration_avoidance.html

Unicode issue

The generated code does not support Unicode as the images below. Could I miss something?

Screen Shot 2022-09-30 at 10 23 25

Screen Shot 2022-09-30 at 10 23 51

[Question] Available locales from i18n4kConfig

Heyo comahe-de,

is it possible to get a list of available i18n locales from the config object?
Say we've got multiple language-bundles in a project: en_GB, de_DE so on and so forth
Would it be possible to somehow retrieve a list which reflects those bundle-locales?

Cheers,
Griefed

Multi-project issue

When using i18n4k with multiple projects that has i18n4k plugin applied to it, the following error occurs:

Execution failed for task ':first-project:jsProcessResources'.
> Entry index.html is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.0/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

Get a translation through an identifier

Hello, good afternoon.

I am using the lib to manage the translations of a desktop app but I need to get the translations through an identifier sent from the backend, is it possible?.

For example, the backend sends ID_SMS and has a method like MYMESSAGE.fromKey("ID_SMS") and returns me the translation.

Unresolved reference: MyMessages

When I use i18n4k with IntelliJ IDEA, I will get an Unresolved reference: MyMessages error every time I use:

println(MyMessages.sayHello("i18n4k"))

I know this is because the code will be generated after and this won't affect the functionality, but is there any way to disable the error for the MyMessages class so that my IDE won't show me an error every time I use i18n?

Best regards,

Nativ compilation not working with Kotlin 1.6.21

After switching to Kotlin 1.6.21, the native source set does not compile any more:

e: C:\git\github\comahe-de\i18n4k\i18n4k-core\src\nativeMain\kotlin\de\comahe\i18n4k\Locale.kt: (22, 39): Unresolved reference: toTag

How to handle same language for different countries

Hi,

How do I handle the same languages for different countries?

For example:

  • en_US and en_CA
  • pt_BR and pt_PT
  • es_ES and es_AR

I tried to name the properties files with language_COUNTRY and pass the full locale Locale("pt", "BR") but that did not work.

Problem with Gradle 7

Hi,

I really like the library and what it can already do!! I set it up as a proof of concept and got it working after some troubles. Now I had to upgrade to the latest gradle version because of another plugin and I am now getting this error:

* What went wrong:
A problem was found with the configuration of task ':coreLibs:generateI18n4kFiles' (type 'GenerateI18n4kFilesTask').
  - In plugin 'de.comahe.i18n4k' type 'de.comahe.i18n4k.gradle.plugin.GenerateI18n4kFilesTask' property 'config' is missing an input or output annotation.
    
    Reason: A property without annotation isn't considered during up-to-date checking.
    
    Possible solutions:
      1. Add an input or output annotation.
      2. Mark it as @Internal.
    
    Please refer to https://docs.gradle.org/7.1.1/userguide/validation_problems.html#missing_annotation for more details about this problem.

This is blocking us from adding it to our production code. Would be great to see a fix :)
I haven't really worked on kotlin plugins, but if this takes longer I might give it a try to provide a PR sometime next week. So please let me know if this would help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.