hyperdevs-team / poeditor-android-gradle-plugin Goto Github PK
View Code? Open in Web Editor NEWGradle plug-in that enables importing PoEditor localized strings directly to an Android project
License: Apache License 2.0
Gradle plug-in that enables importing PoEditor localized strings directly to an Android project
License: Apache License 2.0
SW details (please complete the following information):
Summary and background of the bug
Having a string like the following in POEditor:
<![CDATA[
<br />
<p><a href="mailto:[email protected]">ABC Email</a></p>
]]>
Makes the plugin to crash and never download the strings.
Steps to reproduce
Steps to reproduce the behaviour:
> org.xml.sax.SAXParseException; lineNumber: 147; columnNumber: 235; The element type "p" must be terminated by the matching end-tag "</p>".
I followed the exception and found that
String.unescapeHtmlTags()
doesn't do its job of replaces all html tags, mostly it will fail to replace
**<a href="mailto:[email protected]">**ABC Email</a>
so I used this piece of code to fix the issue locally instead of changing the regex used:
fun String.unescapeHtmlTags(): String {
return this.replace("<", "<").replace(">", ">")
}
and it's working very well now.
SW details (please complete the following information):
Summary and background of the bug
The task importPoEditorStrings
fails more than once for all devs with java.net.SocketTimeoutException
. This happens way too often and also on CI which breaks our builds.
Steps to reproduce
Steps to reproduce the behavior:
Not-so-helpful stack trace:
* What went wrong:
Execution failed for task ':data-translations:importPoEditorStrings'.
> java.net.SocketTimeoutException: timeout
Expected behavior
Translations should download unless the server is actually down
Current behavior
Task fails to download translations quite often due to SocketTimeoutException
Additional context
Add any other context about the problem here.
Summary and context of the enhancement
It would be handy to create some guidelines for setting up the project and how to submit contributions (apart from the PR templates)
Suggested implementation
We should take a look to how open-source projects do this so we can have an idea of what is important for contributors to have in the guidelines.
SW details (please complete the following information):
Summary and background of the bug
Languages with empty translations returns empty updated data string from POEditor API which causes an error.
JSON fetched from POEditor:
{
"response":{
"status":"success",
"code":"200",
"message":"OK"
},
"result":{
"languages":[
{
"name":"English",
"code":"en",
"translations":2,
"percentage":100,
"updated":"2021-02-22T07:32:39+0000"
},
{
"name":"German",
"code":"de",
"translations":0,
"percentage":0,
"updated":""
}
]
}
}
Steps to reproduce
Steps to reproduce the behavior:
Stacktrace
Caused by: java.text.ParseException: Unparseable date: ""
at com.bq.poeditor.gradle.utils.DateJsonAdapter.fromJson(DateJsonAdapter.kt:39)
at com.bq.poeditor.gradle.utils.DateJsonAdapter.fromJson(DateJsonAdapter.kt:29)
Expected behavior
Download empty translations without any problem.
Current behavior
Error occurs java.text.ParseException: Unparseable date: ""
.
Great project. I am using to convert my strings from PoEditor. However, I am running into problems with the format of the generated values folders. For example,
values-zh-CN - android studio does not like the format and expects it the CH to be prefaced with an r. Further, any secondary region specifier should be prefaced with an r in my understanding.
Please help.
Summary and context of the enhancement
As per discussed in #17, with the removal of resDirPath
and the obligation of only being able to use the plugin in application modules in version 1.0.0 of the plug-in, support for library modules was dropped since you could no longer set-up a custom path. This issue aims to add proper support for library modules, so we can have tasks to import PoEditor strings from both application and library modules, and call them using the usual ./gradlew :your_module:importPoEditorStrings
.
Suggested implementation
Check if we can implement support for library projects using LibraryExtension
and LibraryPlugin
Additional documentation
Check out
As for the title the error message it's the same
"The entity name must immediately follow the '&' in the entity reference"
tested also on version 3.3.1 and this version doesn't have this issue.
Thanks
Android doesn't support some of the Html tags (eg., <br/>
) from string resource. In such cases, it has to be formatted using Html.fromHtml(), which expects the angle brackets in encoded format (<
), and set to the corresponding TextView in code. So, if we append html with the key, then the angle brackets have to be in encoded format.
SW details (please complete the following information):
Summary and background of the bug
When running the importPoEditorStrings
Gradle task, after the files are properly downloaded and saved:
Retrieving project languages...
Available languages: [en]
Retrieving translation file URL for language code: en
Downloading file from URL: https://api.poeditor.com/v2/download/file/...
Saving strings to /Users/.../Workspace/.../app/src/main/res/values
Gradle throws the following error:
FAILURE: Build failed with an exception.
* What went wrong:
Configuration cache problems found in this build.
- Task `:app:importPoEditorStrings` of type `com.hyperdevs.poeditor.gradle.tasks.ImportPoEditorStringsTask`: invocation of 'Task.project' at execution time is unsupported.
See https://docs.gradle.org/8.5/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
I've tested this on Gradle 8.2 and 8.5, same result.
I've tested the following library versions:
Summary and context of the enhancement
When importing translations from POEditor, terms that are currently not translated to a given language must be removed.
Android Studio/Gradle's default behavior on blank but defined strings is to actually blank the text out instead of using the default (from values). This causes the app to crash, notably if it uses placeholders.
Support for several poeditor project ids
We have split all our strings to several poeditor projects - analytics, links, common strings. It will be great to support several projectId's in configuration.
SW details (please complete the following information):
Summary and background of the bug
We use a lot of emojis on poeditor and when we import terms some emojis are html encoded.
Android Studio is working great with emojis and it would be nice and easier to read if all emojis was not html encoded.
For exemple:
<string name="term_with_emoji">"❤️"</string>
<string name="term_with_emoji_encoded">"😢"</string>
Steps to reproduce
Steps to reproduce the behavior:
Expected behavior
Does not html encode emojis for better readability
Current behavior
Some emojis (but not all) are html encode
Summary and context of the enhancement
Add support for multiple build types' translations in the plugin, so we can import different projects for them.
Suggested implementation
The ideal thing would be to get some configuration like this so we can easily configure it in Gradle scripts:
poEditor {
// General configuration, in case we don't define build type specific configuration
apiToken = "your_api_token"
projectId = 12345
defaultLang = "en"
resDirPath = "${project.rootDir}/app/src/main/res"
// Configuration for flavor1, overrides general configuration
flavor1 {
apiToken = "your_api_token"
projectId = 23456
defaultLang = "en"
resDirPath = "${project.rootDir}/app/src/flavor1/res"
}
...
}
Additional documentation
We should check other Gradle plugins so we can get info about how to do this.
https://jitpack.io/#hyperdevs-team/poeditor-android-gradle-plugin
As you can see the 2.4.1 release is not available there. Can you please upload this version?
The strings.xml file for Indonesian is exported to values-id
but changing the device language to Indonesian has no effect on the app. If the file is in values-in
however, it works as expected.
Another thing I noticed is that both id
and in
are listed as Indonesian in Android Studio's Translations Editor, but on the phone itself only in
is working. This seems to be more of a Java/Android issue, since the official ISO 639-1 is in fact id
.
I think this is also the case for Hebrew and Yiddish: https://developer.android.com/reference/java/util/Locale.html#Locale(java.lang.String)
ISO 639 is not a stable standard; some of the language codes it defines (specifically "iw", "ji", and "in") have changed. This constructor accepts both the old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other API on Locale will return only the OLD codes.
The XML parser throws some exceptions because of this tablet generation.
Mainly, when there are HTML Strings
Though my project contains non-empty strings, the plugin throws the following error. If you want I can share my poeditor credentials privately with you. I'm using com.github.imartinez:poeditor-android-gradle-plugin:0.2.6. But, I think that doesn't matter, because I encountered the same error with com.github.bq:poeditor-android-gradle-plugin:0.2.5 also.
`:app:importPoEditorStrings FAILED
FAILURE: Build failed with an exception.
Text must not be null or empty
Try:
Run with --info or --debug option to get more log output.
Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:importPoEditorStrings'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:84)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:196)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:193)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:193)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:44)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:29)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.IllegalArgumentException: Text must not be null or empty
at com.bq.gradle.ImportPoEditorStringsTask.importPoEditorStrings(ImportPoEditorStringsTask.groovy:58)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:141)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:123)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:632)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:615)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:95)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:76)
... 70 more
BUILD FAILED`
Hi there,
Im trying to import the plugin with the new Gradle format like bellow,
plugins {
id 'com.android.application' version "$gradlePluginVersion" apply false
id 'com.android.library' version "$gradlePluginVersion" apply false
id 'org.jetbrains.kotlin.android' version "$kotlinPluginVersion" apply false
id 'com.github.hyperdevs-team.poeditor-android-gradle-plugin' version "$poEditorPluginVersion" apply false
}
But Im always getting the bellow error:
Plugin [id: 'com.github.hyperdevs-team.poeditor-android-gradle-plugin', version: '3.4.0', apply: false] was not found in any of the following sources:
What is the correct ID?
Thank you,
Best regards,
Bernardo
Summary and context of the enhancement
Hello guys, in the configuration of the import
poEditor {
apiToken = "your_api_token"
projectId = 12345
defaultLang = "en"
}
I am missing a config property for comments.
My strings import is always with them included, which makes the final resource file kinda bloated.
<string>abc</string>
<!--comment related to "def"-->
<string>def</string>
It is only comments, which is not crucial, but still you can introduce a lot of unnecessary things like TODOs, unrelated information, etc.
I haven't found how to omit them in the import.
Suggested implementation
Just a boolean property on the config would be great.
poEditor {
apiToken = "your_api_token"
projectId = 12345
defaultLang = "en"
**importComments = false**
}
Thanks!
Summary and context of the enhancement
API v1 has been deprecated, so we need to migrate to v2.
Suggested implementation
https://poeditor.com/api/
to https://api.poeditor.com/v2/
and adapt the data model, endpoints etc according to the new API.Additional documentation
https://poeditor.com/docs/api
SW details (please complete the following information):
Summary and background of the bug
As reported by @nokite in #37:
Btw I often have trouble with detekt. Like now when merging master into my branch.
When there's a problem and the commit/merge commit is blocked, the error output is hard to read, it's all in one line 🙂
Maybe it's not correctly set up on my machine, didn't spend time on this.Here's some output. In this case it's actually pretty short, but normally it also mentions some formatting/complexity warnings etc. (and it's all in one line)
Couldn't check the working tree for unmerged files because of an error. tput: No value for $TERM and no -T specified tput: No value for $TERM and no -T specified tput: No value for $TERM and no -T specified tput: No value for $TERM and no -T specified Running detekt > Task :detekt UP-TO-DATE Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.9/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 814ms 1 actionable task: 1 up-to-date Your code is properly formatted! could not read log file '/Users/.../poeditor-android-gradle-plugin/.git/MERGE_MSG': No such file or directory
`./gradlew importPoEditorStrings --stacktrace
Task :myProject:importPoEditorStrings FAILED
Retrieving project languages...
An error happened when retrieving strings from project. Please review the plug-in's input parameters and try again
FAILURE: Build failed with an exception.
Required value 'result' missing at $
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.
Summary and context of the enhancement
In our project we use html tags combined with format strings. That means that tags should be escaped. It would be great to have that option.
Suggested implementation
Add an attribute unescapeHtmlTags to poEditor section with default value true. And than in XmlPostProcessor.formatTranslationString() check that attribute
Additional documentation
About
https://developer.android.com/guide/topics/resources/string-resource.html#StylingWithHTML
SW details:
Summary and background of the bug
JCenter may stop working in February 2022, so it should be removed from the project. Any dependencies should be fetched from other repositories.
The shutdown date of the repository itself is not clear. In reality it might keep working in read-only mode for a longer time. But no guarantees are given after February.
Furthermore, Gradle 8 will remove jcenter().
I have been working on a project with 10000 lines of stings. I am deciding to split them up into small projects for better management.
Can you please update the PoEditorStringsImporter.kt for handling a list of project IDs in order to get translations from multiple projects.
SW details (please complete the following information):
Summary and background of the bug
In the documentation it's mentioned that it's possible to send order in the parameters but I belive in the latest gradle settings it's not working because it's missing a setter. Something like this for example:
fun setDefaultLang(value: String) = defaultLang.set(value)
This is not available for order
Steps to reproduce
Steps to reproduce the behavior:
A problem occurred evaluating project ':app'.
Could not set unknown property 'order' for extension 'poEditor' of type com.hyperdevs.poeditor.gradle.PoEditorPluginExtension.
Expected behavior
Value would be set in the request to poeditor and terms would arrive ordered
Current behavior
Crashes. Exception in pasted above.
Additional context
Nothing else.
SW details (please complete the following information):
Build time: 2020-02-17 08:32:01 UTC
Revision: 61d3320259a1a0d31519bf208eb13741679a742f
Kotlin: 1.3.61
Groovy: 2.5.8
Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM: 1.8.0_231 (Oracle Corporation 25.231-b11)
OS: Mac OS X 10.16 x86_64
Summary and background of the bug
Simplified Chinese is downloaded to values-zh-rHANS
and Traditional Chinese to values-zh-tHANT
. They should probably be in values-b+zh+Hans
and values-b+zh+Hant
respectively.
Steps to reproduce
Steps to reproduce the behavior:
Expected behavior
Translations should probably be in values-b+zh+Hans
and values-b+zh+Hant
respectively.
Current behavior
Simplified Chinese is downloaded to values-zh-rHANS
and Traditional Chinese to values-zh-tHANT
SW details (please complete the following information):
Summary and background of the bug
After updating the android gradle plugin from 7.0.4 to 7.1.0, an error occurs when building.
I think ApplicationAndroidComponentsExtension was deprecated.
Steps to reproduce
Steps to reproduce the behavior:
SW details
Summary and background of the bug
Html based strings wrapped by <![CDATA[ ]]>
on POEditor are imported without <![CDATA[ ]]>
via plugin
Steps to reproduce
Steps to reproduce the behavior:
<![CDATA[Some text<a href="%1$s">Link</a> text text]]>
<![CDATA[ ]]>
is missed<string name="test_string_id">"Some text<a href="%1$s">Link</a> text text"</string>
Expected behavior
Imported strings should contain <![CDATA[ ]]>
Current behavior
<![CDATA[ ]]>
is missed
Additional context
When strings are exported via POEditor web page, they contain <![CDATA[ ]]>
Summary and context of the enhancement
This is a resurrection of the issue #49. In our project we use HTML tags combined with format strings. That means that tags should be escaped. It would be great to have that option.
Suggested implementation
Add an attribute unescapeHtmlTags to poEditor section with default value true, and enable/disable string escaping based on this value.
Additional documentation
https://developer.android.com/guide/topics/resources/string-resource.html#StylingWithHTML
In some cases, however, you may want to create a styled text resource that is also used as a format string. Normally, this doesn't work [...] The work-around to this is to write the HTML tags with escaped entities.
Summary and context of the enhancement
As an user I want to download the strings for specific module based on a given tag(s).
Suggested implementation
Added a new configuration to the poEditor receiving an array of tags.
On the poEditor API request send the list of tags to poEditor API, poEditor will filter the strings by tag(s)
SW details (please complete the following information):
Summary and background of the bug
Tags intersection doesn't work when specifying a list of tags. The plugin just pulls in all strings, not an intersection of the tags as it's supposed to.
I assume this is caused by the way the tags are being sent using Retrofit. They should be sent as tags : ["tagA", "tagB"]
(https://poeditor.com/docs/api#projects_export_example_1_button). I haven't been able to check it, but I assume currently they are being sent as tags : tagA, tagB
Steps to reproduce
Steps to reproduce the behavior:
Expected behavior
Only string 1 should be pulled.
Current behavior
Currently both strings are pulled.
SW details (please complete the following information):
Summary and background of the bug
When applying the plugin to a project I get the following error:
A problem occurred configuring project ':app'.
> Cannot query the value of extension 'poEditor' property 'enabled' because it has no value available.
Steps to reproduce
Steps to reproduce the behavior:
I have replicated this on my work project and also tired it in a new bare bones Android project. I have attached the project for replication purposes.
If you need any more info let me know.
Expected behavior
The sync should pass without error.
Additional context
Add any other context about the problem here.
`* What went wrong:
Execution failed for task ':app:importPoEditorStrings'.
java.io.IOException: Cannot run program "curl": CreateProcess error=2, The system cannot find the file specified
Try:
Run with --info or --debug option to get more log output.
Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:importPoEditorStrings'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:84)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:236)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:228)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:215)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:77)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:58)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:32)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:113)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:196)
at org.gradle.initialization.DefaultGradleLauncher$3.execute(DefaultGradleLauncher.java:193)
at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:193)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:44)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:29)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.UncheckedIOException: java.io.IOException: Cannot run program "curl": CreateProcess error=2, The system cannot find the file specified
at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:43)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:76)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:141)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:123)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:632)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:615)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:95)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:76)
... 70 more
Caused by: java.io.IOException: Cannot run program "curl": CreateProcess error=2, The system cannot find the file specified
at com.bq.gradle.ImportPoEditorStringsTask.importPoEditorStrings(ImportPoEditorStringsTask.groovy:57)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
... 77 more
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
... 79 more
`
Can you provide a fix asap?
Summary and context of the enhancement
Right now the plugin doesn't handle Android plurals properly.
Plurals' syntax is slightly different from the usual <string>
nodes, as they follow this structure:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals
name="plural_name">
<item
quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
>text_string</item>
</plurals>
</resources>
We need to be able to provide the same functionality that we do for simple strings to plural strings.
It may also be handy to ensure that we add at least one number to the placeholders, but for the initial approach it might not be needed.
Suggested implementation
No suggested implementation.
Additional documentation
Android information about plurals string resources: https://developer.android.com/guide/topics/resources/string-resource#Plurals
SW details (please complete the following information):
Summary and background of the bug
All the occurrences of "%" are doubled.
Eg.
Another problem: all the string have been put into quotation marks
Eg.
Steps to reproduce
Just execute: gradlew importPoEditorStrings
Expected behavior
I expect that these parameters ("%") string stay unattached
Current behavior
All the occurrences of "%" are doubled.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.