Conversation
a09386a to
496daad
Compare
| viewModel: StoneCameraViewModel, | ||
| previousMode: String, | ||
| nextMode: String | ||
| previousMode: TranslatableString, |
There was a problem hiding this comment.
is it possible to keep original String type?
|
|
||
| override val modeLabel | ||
| get() = "video" | ||
| get() = @Translatable "video".i18n() |
There was a problem hiding this comment.
looks a bit too "bulky"
is there any options to use only either annotation or i18n() method?
There was a problem hiding this comment.
Assuming that this approach is quite bulky, there may be cases where someone simply hard codes a string without using @Translatable or calling .i18n(). This would mean that string wouldn't be considered for translation and the app would ship with hardcoded strings. How might we check for this happening to reduce the likelihood the app is shipped with hardcoded strings rather than translatable/translated strings?
| val controlModeGet = viewModel.getSetting<TranslatableString>("volumeControlMode") | ||
|
|
||
| if (isZoomMode || controlModeGet == "Zoom") { | ||
| if (isZoomMode || controlModeGet?.resolve() == "Zoom") { |
There was a problem hiding this comment.
.resolve() == "Zoom"
will it still work in different langs?
| } | ||
|
|
||
| private fun sanitizeKey(key: String): String { | ||
| val sanitized = key.replace(Regex("[^a-zA-Z0-9]"), "_") |
There was a problem hiding this comment.
not a collision proof solution
a sanitized key for "!Test" will be equal to the key for "?Test"
There was a problem hiding this comment.
potentially different parts of the app could have same strings in english but with different translations to other languages
so i would suggest to introduce a module prefix for keys
There was a problem hiding this comment.
Also, for example some strings in English are written the same but have very different meanings so the same translation might not suit each use of what is lexically a common string. I'll provide a small example: "row" as in a row in a spreadsheet is not the same word as "row" as in two people had a row, or to row a boat.
| Text(text = modeLabel.uppercase(), | ||
| color = if (modeLabel == selectedMode) Color(0xFFFFCC00) else Color.White, | ||
| Text(text = modeLabel.resolve().uppercase(), | ||
| color = if (modeLabel.resolve() == selectedMode.resolve()) Color(0xFFFFCC00) else Color.White, |
There was a problem hiding this comment.
as i've got you can leave it as it was modeLabel == selectedMode
| sourceDir.walkTopDown() | ||
| .filter { it.isFile && it.extension in listOf("kt", "java") } | ||
| .forEach { file -> | ||
| val regex = Regex("@Translatable\\s*\\\"(.*?)\\\"") |
There was a problem hiding this comment.
cuts the string if you put \" in the middle
There was a problem hiding this comment.
Sounds like having automated test cases that check the translation will behave as desired even for multi-line strings, etc. might be useful at checking whether these sorts of regex mistakes are dealt with?
| /** | ||
| * Sanitizes a string to make it a valid XML key. | ||
| */ | ||
| private fun sanitizeKey(key: String): String { |
There was a problem hiding this comment.
duplicated logic with
julianharty
left a comment
There was a problem hiding this comment.
Overall I like this innovative approach to bootstrap translations of textual strings and it's a really nice idea. For production use I suspect the project may need suitably competent humans-in-the-loop for the translations, at least for a while.
It's probably worth another round of code reviews if you decide to refine the code based on my and other reviewer's comments. Happy to do so.
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
|
|
||
| TranslationManager.loadTranslationsForLocale(applicationContext) |
There was a problem hiding this comment.
Does this guarantee to return a set of elements (translations) regardless of the application's context? In other words are there ever going to be cases where it wouldn't return a) something the program can run with, b) something the human user can understand?
|
|
||
| TranslationManager.loadTranslationsForLocale(applicationContext) | ||
|
|
||
| if (!isChromeOS()) { |
There was a problem hiding this comment.
Dumb question and not directly part of this PR... Are we targeting ChromeOS?
There was a problem hiding this comment.
With the removal of android.util.log what's happening about logging?
| workList.awaitAll() | ||
| Log.d("Analyzer", "All plugins completed successfully") | ||
| } catch (e: Exception) { | ||
| Log.e("Analyzer", "Error in one or more plugins", e) |
There was a problem hiding this comment.
Again a question not directly part of this PR, but triggered when reading the code deleted above, what happens with the worklist.awaitAll() if an exception occurs in one or more of the plugins that are running in parallel?
| }, | ||
| renderLocation = SettingLocation.TOP, | ||
| label = "Aspect Ratio" | ||
| label = @Translatable "Aspect Ratio".i18n() |
There was a problem hiding this comment.
How does this call respond if a match isn't found for the string being translated?
There was a problem hiding this comment.
There's the potential for translated strings to require significant changes to screen real-estate for various reasons such as phrasing in that locale, to mistranslations, to nefarious attacks. Probably worth adding some forms of sanity checking of translated strings before they're incorporated into an app.
There was a problem hiding this comment.
How long is the translation expected to take? and is the translation process intended to complete before the app is compiled? Oh, and are the translations something that are expected to be added into a git repo or simply processed on the build machine (which may be an ephemeral computer in the cloud)? I expect that auditability of translations (localisations) will be key at various times in the life of the project, sometimes long after the event that performed the translation/localisation, so auditing and maintaining easily readable snapshots might also be key to do.
| abstract val resDir: DirectoryProperty | ||
|
|
||
| private val apiKey: String = | ||
| System.getenv("OPENAI_API_KEY") ?: error("OPENAI_API_KEY environment variable not set") |
There was a problem hiding this comment.
I think this topic has already been mentioned in discussion so this is more of a reminder that relying on OpenAI (or other similar services) might be problematic from a legal/licensing perspective as and when the app is in production use.
There was a problem hiding this comment.
How about adding logging to this file as a partial approach to maintaining a record of what's happening?
| language: String | ||
| ): String { | ||
| val languageName = when (language) { | ||
| "es" -> "Spanish" |
There was a problem hiding this comment.
These are great from a proof-of-concept point-of-view. Worth considering supporting locales rather than raw language codes e.g. to support es_MX for Mexican Spanish, etc.
| sourceDir.walkTopDown() | ||
| .filter { it.isFile && it.extension in listOf("kt", "java") } | ||
| .forEach { file -> | ||
| val regex = Regex("@Translatable\\s*\\\"(.*?)\\\"") |
There was a problem hiding this comment.
Sounds like having automated test cases that check the translation will behave as desired even for multi-line strings, etc. might be useful at checking whether these sorts of regex mistakes are dealt with?
How to make a string auto-internationalise: