Merge remote-tracking branch 'github/main'

This commit is contained in:
Ilya 2026-02-10 21:28:54 +03:00
commit b24f189da2
42 changed files with 741 additions and 328 deletions

View File

@ -26,54 +26,33 @@ concurrency:
jobs: jobs:
# Prepare environment and build the plugin # Prepare the environment and build the plugin
build: build:
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs:
version: ${{ steps.properties.outputs.version }}
changelog: ${{ steps.properties.outputs.changelog }}
pluginVerifierHomeDir: ${{ steps.properties.outputs.pluginVerifierHomeDir }}
steps: steps:
# Check out current repository # Free GitHub Actions Environment Disk Space
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false
# Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
# Validate wrapper # Set up the Java environment for the next steps
- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2
# Set up Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Setup Gradle # Setup Gradle
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/actions/setup-gradle@v4
with:
gradle-home-cache-cleanup: true
# Set environment variables
- name: Export Properties
id: properties
shell: bash
run: |
PROPERTIES="$(./gradlew properties --console=plain -q)"
VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "pluginVerifierHomeDir=~/.pluginVerifier" >> $GITHUB_OUTPUT
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier
# Build plugin # Build plugin
- name: Build plugin - name: Build plugin
@ -90,7 +69,7 @@ jobs:
echo "filename=${FILENAME:0:-4}" >> $GITHUB_OUTPUT echo "filename=${FILENAME:0:-4}" >> $GITHUB_OUTPUT
# Store already-built plugin as an artifact for downloading # Store an already-built plugin as an artifact for downloading
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@ -104,22 +83,29 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# Check out current repository # Free GitHub Actions Environment Disk Space
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false
# Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
# Set up Java environment for the next steps # Set up the Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Setup Gradle # Setup Gradle
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/actions/setup-gradle@v4
with: with:
gradle-home-cache-cleanup: true cache-read-only: true
# Run tests # Run tests
- name: Run Tests - name: Run Tests
@ -135,11 +121,12 @@ jobs:
# Upload the Kover report to CodeCov # Upload the Kover report to CodeCov
- name: Upload Code Coverage Report - name: Upload Code Coverage Report
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
files: ${{ github.workspace }}/build/reports/kover/report.xml files: ${{ github.workspace }}/build/reports/kover/report.xml
token: ${{ secrets.CODECOV_TOKEN }}
# Run Qodana inspections and provide report # Run Qodana inspections and provide a report
inspectCode: inspectCode:
name: Inspect code name: Inspect code
needs: [ build ] needs: [ build ]
@ -152,25 +139,28 @@ jobs:
# Free GitHub Actions Environment Disk Space # Free GitHub Actions Environment Disk Space
- name: Maximize Build Space - name: Maximize Build Space
uses: jlumbroso/free-disk-space@main uses: jlumbroso/free-disk-space@v1.3.1
with: with:
tool-cache: false tool-cache: false
large-packages: false large-packages: false
# Check out current repository # Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
# Set up Java environment for the next steps # Set up the Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Run Qodana inspections # Run Qodana inspections
- name: Qodana - Code Inspection - name: Qodana - Code Inspection
uses: JetBrains/qodana-action@v2023.3.1 uses: JetBrains/qodana-action@v2025.1.1
with: with:
cache-default-branch-only: true cache-default-branch-only: true
@ -183,38 +173,31 @@ jobs:
# Free GitHub Actions Environment Disk Space # Free GitHub Actions Environment Disk Space
- name: Maximize Build Space - name: Maximize Build Space
uses: jlumbroso/free-disk-space@main uses: jlumbroso/free-disk-space@v1.3.1
with: with:
tool-cache: false tool-cache: false
large-packages: false large-packages: false
# Check out current repository # Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
# Set up Java environment for the next steps # Set up the Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Setup Gradle # Setup Gradle
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/actions/setup-gradle@v4
with: with:
gradle-home-cache-cleanup: true cache-read-only: true
# Cache Plugin Verifier IDEs
- name: Setup Plugin Verifier IDEs Cache
uses: actions/cache@v4
with:
path: ${{ needs.build.outputs.pluginVerifierHomeDir }}/ides
key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }}
# Run Verify Plugin task and IntelliJ Plugin Verifier tool # Run Verify Plugin task and IntelliJ Plugin Verifier tool
- name: Run Plugin Verification tasks - name: Run Plugin Verification tasks
run: ./gradlew runPluginVerifier -Dplugin.verifier.home.dir=${{ needs.build.outputs.pluginVerifierHomeDir }} run: ./gradlew verifyPlugin
# Collect Plugin Verifier Result # Collect Plugin Verifier Result
- name: Collect Plugin Verifier Result - name: Collect Plugin Verifier Result
@ -225,7 +208,7 @@ jobs:
path: ${{ github.workspace }}/build/reports/pluginVerifier path: ${{ github.workspace }}/build/reports/pluginVerifier
# Prepare a draft release for GitHub Releases page for the manual verification # Prepare a draft release for GitHub Releases page for the manual verification
# If accepted and published, release workflow would be triggered # If accepted and published, the release workflow would be triggered
releaseDraft: releaseDraft:
name: Release draft name: Release draft
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
@ -235,7 +218,7 @@ jobs:
contents: write contents: write
steps: steps:
# Check out current repository # Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -253,10 +236,11 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
gh release create "v${{ needs.build.outputs.version }}" \ VERSION=$(./gradlew properties --property version --quiet --console=plain | tail -n 1 | cut -f2- -d ' ')
RELEASE_NOTE="./build/tmp/release_note.txt"
./gradlew getChangelog --unreleased --no-header --quiet --console=plain --output-file=$RELEASE_NOTE
gh release create $VERSION \
--draft \ --draft \
--title "v${{ needs.build.outputs.version }}" \ --title $VERSION \
--notes "$(cat << 'EOM' --notes-file $RELEASE_NOTE
${{ needs.build.outputs.changelog }}
EOM
)"

View File

@ -1,5 +1,5 @@
# GitHub Actions Workflow created for handling the release process based on the draft release prepared with the Build workflow. # GitHub Actions Workflow created for handling the release process based on the draft release prepared with the Build workflow.
# Running the publishPlugin task requires all following secrets to be provided: PUBLISH_TOKEN, PRIVATE_KEY, PRIVATE_KEY_PASSWORD, CERTIFICATE_CHAIN. # Running the publishPlugin task requires all the following secrets to be provided: PUBLISH_TOKEN, PRIVATE_KEY, PRIVATE_KEY_PASSWORD, CERTIFICATE_CHAIN.
# See https://plugins.jetbrains.com/docs/intellij/plugin-signing.html for more information. # See https://plugins.jetbrains.com/docs/intellij/plugin-signing.html for more information.
name: Release name: Release
@ -18,46 +18,43 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
# Check out current repository # Free GitHub Actions Environment Disk Space
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false
# Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.release.tag_name }} ref: ${{ github.event.release.tag_name }}
# Set up Java environment for the next steps # Set up the Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Setup Gradle # Setup Gradle
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/actions/setup-gradle@v4
with: with:
gradle-home-cache-cleanup: true cache-read-only: true
# Set environment variables # Update the Unreleased section with the current release note
- name: Export Properties
id: properties
shell: bash
run: |
CHANGELOG="$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'
${{ github.event.release.body }}
EOM
)"
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Update Unreleased section with the current release note
- name: Patch Changelog - name: Patch Changelog
if: ${{ steps.properties.outputs.changelog != '' }} if: ${{ github.event.release.body != '' }}
env: env:
CHANGELOG: ${{ steps.properties.outputs.changelog }} CHANGELOG: ${{ github.event.release.body }}
run: | run: |
./gradlew patchChangelog --release-note="$CHANGELOG" RELEASE_NOTE="./build/tmp/release_note.txt"
mkdir -p "$(dirname "$RELEASE_NOTE")"
echo "$CHANGELOG" > $RELEASE_NOTE
./gradlew patchChangelog --release-note-file=$RELEASE_NOTE
# Publish the plugin to JetBrains Marketplace # Publish the plugin to JetBrains Marketplace
- name: Publish Plugin - name: Publish Plugin
@ -68,7 +65,7 @@ jobs:
PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }} PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
run: ./gradlew publishPlugin run: ./gradlew publishPlugin
# Upload artifact as a release asset # Upload an artifact as a release asset
- name: Upload Release Asset - name: Upload Release Asset
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -31,22 +31,22 @@ jobs:
steps: steps:
# Check out current repository # Check out the current repository
- name: Fetch Sources - name: Fetch Sources
uses: actions/checkout@v4 uses: actions/checkout@v4
# Set up Java environment for the next steps # Set up the Java environment for the next steps
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 21
# Setup Gradle # Setup Gradle
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/actions/setup-gradle@v4
with: with:
gradle-home-cache-cleanup: true cache-read-only: true
# Run IDEA prepared for UI testing # Run IDEA prepared for UI testing
- name: Run IDE - name: Run IDE
@ -54,7 +54,7 @@ jobs:
# Wait for IDEA to be started # Wait for IDEA to be started
- name: Health Check - name: Health Check
uses: jtalk/url-health-check-action@v3 uses: jtalk/url-health-check-action@v4
with: with:
url: http://127.0.0.1:8082 url: http://127.0.0.1:8082
max-attempts: 15 max-attempts: 15

3
.gitignore vendored
View File

@ -1,4 +1,7 @@
.DS_Store
.gradle .gradle
.idea .idea
.intellijPlatform
.kotlin
.qodana .qodana
build build

View File

@ -1,25 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run IDE for UI Tests" type="GradleRunConfiguration" factoryName="Gradle">
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIdeForUiTests" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Plugin" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="Run Plugin" type="GradleRunConfiguration" factoryName="Gradle">
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" /> <log_file alias="IDE logs" path="$PROJECT_DIR$/build/idea-sandbox/*/log/idea.log" show_all="true" />
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
@ -19,6 +19,7 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>

View File

@ -1,24 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Qodana" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="qodanaScan" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>

View File

@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Verifications" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="Run Tests" type="GradleRunConfiguration" factoryName="Gradle">
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" /> <log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
@ -11,7 +11,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="runPluginVerifier" /> <option value="check" />
</list> </list>
</option> </option>
<option name="vmOptions" value="" /> <option name="vmOptions" value="" />
@ -19,8 +19,7 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<method v="2"> <RunAsTest>true</RunAsTest>
<option name="Gradle.BeforeRunTask" enabled="true" tasks="clean" externalProjectPath="$PROJECT_DIR$" vmOptions="" scriptParameters="" /> <method v="2" />
</method>
</configuration> </configuration>
</component> </component>

View File

@ -11,7 +11,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="runPluginVerifier" /> <option value="verifyPlugin" />
</list> </list>
</option> </option>
<option name="vmOptions" value="" /> <option name="vmOptions" value="" />
@ -19,8 +19,7 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<method v="2"> <RunAsTest>false</RunAsTest>
<option name="Gradle.BeforeRunTask" enabled="true" tasks="clean" externalProjectPath="$PROJECT_DIR$" vmOptions="" scriptParameters="" /> <method v="2" />
</method>
</configuration> </configuration>
</component> </component>

View File

@ -4,6 +4,52 @@
## [Unreleased] ## [Unreleased]
### Changed
- Use textarea component for translation dialog locale values (#477)
## [4.8.1] - 2025-09-04
### Changed
- Update dependencies
## [4.8.0] - 2025-04-25
### Added
- Support for IntelliJ Platform version 2025.1
### Changed
- Dropped support for platform builds below 2024.2
- Build using Java 21
- Update dependencies
## [4.7.0] - 2024-11-23
### Added
- Support for IntelliJ Platform version 2024.3
- Assistance for translation key reference and key completion in HTML files. Thanks to @Adeptius
### Changed
- Require at least IntelliJ Platform version 2023.3.8
- Remove deprecated api usage
## [4.6.0] - 2024-05-31
### Added
- Automated key naming convention suggestion for Localize-It action. Thanks to @JPilson
## [4.5.2] - 2024-05-30
### Added
- Support for IntelliJ Platform version 2024.2
## [4.5.1] - 2024-04-13 ## [4.5.1] - 2024-04-13
### Fixed ### Fixed
@ -453,39 +499,43 @@
- README.md - README.md
[Unreleased]: https://github.com/marhali/easy-i18n/compare/v4.5.1...HEAD [Unreleased]: https://github.com/marhali/easy-i18n/compare/v4.8.0...HEAD
[4.8.0]: https://github.com/marhali/easy-i18n/compare/v4.7.0...v4.8.0
[4.7.0]: https://github.com/marhali/easy-i18n/compare/v4.6.0...v4.7.0
[4.6.0]: https://github.com/marhali/easy-i18n/compare/v4.5.2...v4.6.0
[4.5.2]: https://github.com/marhali/easy-i18n/compare/v4.5.1...v4.5.2
[4.5.1]: https://github.com/marhali/easy-i18n/compare/v4.5.0...v4.5.1 [4.5.1]: https://github.com/marhali/easy-i18n/compare/v4.5.0...v4.5.1
[4.5.0]: https://github.com/marhali/easy-i18n/compare/v4.4.4...v4.5.0 [4.5.0]: https://github.com/marhali/easy-i18n/compare/v4.4.4...v4.5.0
[4.4.4]: https://github.com/marhali/easy-i18n/compare/v4.4.3...v4.4.4 [4.4.4]: https://github.com/marhali/easy-i18n/compare/v4.4.3...v4.4.4
[4.4.3]: https://github.com/marhali/easy-i18n/compare/v4.4.2...v4.4.3 [4.4.3]: https://github.com/marhali/easy-i18n/compare/v4.4.2...v4.4.3
[4.4.2]: https://github.com/marhali/easy-i18n/compare/v4.4.1...v4.4.2 [4.4.2]: https://github.com/marhali/easy-i18n/compare/v4.4.1...v4.4.2
[4.4.1]: null/compare/v4.4.0...v4.4.1 [4.4.1]: https://github.com/marhali/easy-i18n/compare/v4.4.0...v4.4.1
[4.4.0]: null/compare/v4.3.1...v4.4.0 [4.4.0]: https://github.com/marhali/easy-i18n/compare/v4.3.1...v4.4.0
[4.3.1]: null/compare/v4.3.0...v4.3.1 [4.3.1]: https://github.com/marhali/easy-i18n/compare/v4.3.0...v4.3.1
[4.3.0]: null/compare/v4.2.4...v4.3.0 [4.3.0]: https://github.com/marhali/easy-i18n/compare/v4.2.4...v4.3.0
[4.2.4]: null/compare/v4.2.3...v4.2.4 [4.2.4]: https://github.com/marhali/easy-i18n/compare/v4.2.3...v4.2.4
[4.2.3]: null/compare/v4.2.2...v4.2.3 [4.2.3]: https://github.com/marhali/easy-i18n/compare/v4.2.2...v4.2.3
[4.2.2]: null/compare/v4.2.1...v4.2.2 [4.2.2]: https://github.com/marhali/easy-i18n/compare/v4.2.1...v4.2.2
[4.2.1]: null/compare/v4.2.0...v4.2.1 [4.2.1]: https://github.com/marhali/easy-i18n/compare/v4.2.0...v4.2.1
[4.2.0]: null/compare/v4.1.1...v4.2.0 [4.2.0]: https://github.com/marhali/easy-i18n/compare/v4.1.1...v4.2.0
[4.1.1]: null/compare/v4.1.0...v4.1.1 [4.1.1]: https://github.com/marhali/easy-i18n/compare/v4.1.0...v4.1.1
[4.1.0]: null/compare/v4.0.0...v4.1.0 [4.1.0]: https://github.com/marhali/easy-i18n/compare/v4.0.0...v4.1.0
[4.0.0]: null/compare/v3.2.0...v4.0.0 [4.0.0]: https://github.com/marhali/easy-i18n/compare/v3.2.0...v4.0.0
[3.2.0]: null/compare/v3.1.0...v3.2.0 [3.2.0]: https://github.com/marhali/easy-i18n/compare/v3.1.0...v3.2.0
[3.1.0]: null/compare/v3.0.1...v3.1.0 [3.1.0]: https://github.com/marhali/easy-i18n/compare/v3.0.1...v3.1.0
[3.0.1]: null/compare/v3.0.0...v3.0.1 [3.0.1]: https://github.com/marhali/easy-i18n/compare/v3.0.0...v3.0.1
[3.0.0]: null/compare/v2.0.0...v3.0.0 [3.0.0]: https://github.com/marhali/easy-i18n/compare/v2.0.0...v3.0.0
[2.0.0]: null/compare/v1.7.1...v2.0.0 [2.0.0]: https://github.com/marhali/easy-i18n/compare/v1.7.1...v2.0.0
[1.7.1]: null/compare/v1.7.0...v1.7.1 [1.7.1]: https://github.com/marhali/easy-i18n/compare/v1.7.0...v1.7.1
[1.7.0]: null/compare/v1.6.0...v1.7.0 [1.7.0]: https://github.com/marhali/easy-i18n/compare/v1.6.0...v1.7.0
[1.6.0]: null/compare/v1.5.1...v1.6.0 [1.6.0]: https://github.com/marhali/easy-i18n/compare/v1.5.1...v1.6.0
[1.5.1]: null/compare/v1.5.0...v1.5.1 [1.5.1]: https://github.com/marhali/easy-i18n/compare/v1.5.0...v1.5.1
[1.5.0]: null/compare/v1.4.1...v1.5.0 [1.5.0]: https://github.com/marhali/easy-i18n/compare/v1.4.1...v1.5.0
[1.4.1]: null/compare/v1.4.0...v1.4.1 [1.4.1]: https://github.com/marhali/easy-i18n/compare/v1.4.0...v1.4.1
[1.4.0]: null/compare/v1.3.0...v1.4.0 [1.4.0]: https://github.com/marhali/easy-i18n/compare/v1.3.0...v1.4.0
[1.3.0]: null/compare/v1.2.0...v1.3.0 [1.3.0]: https://github.com/marhali/easy-i18n/compare/v1.2.0...v1.3.0
[1.2.0]: null/compare/v1.1.1...v1.2.0 [1.2.0]: https://github.com/marhali/easy-i18n/compare/v1.1.1...v1.2.0
[1.1.1]: null/compare/v1.1.0...v1.1.1 [1.1.1]: https://github.com/marhali/easy-i18n/compare/v1.1.0...v1.1.1
[1.1.0]: null/compare/v1.0.1...v1.1.0 [1.1.0]: https://github.com/marhali/easy-i18n/compare/v1.0.1...v1.1.0
[1.0.1]: null/compare/v1.0.0...v1.0.1 [1.0.1]: https://github.com/marhali/easy-i18n/compare/v1.0.0...v1.0.1
[1.0.0]: null/commits/v1.0.0 [1.0.0]: https://github.com/marhali/easy-i18n/commits/v1.0.0

View File

@ -1,80 +1,71 @@
import org.jetbrains.changelog.Changelog import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
fun properties(key: String) = providers.gradleProperty(key)
fun environment(key: String) = providers.environmentVariable(key)
plugins { plugins {
id("java") // Java support id("java") // Java support
alias(libs.plugins.kotlin) // Kotlin support alias(libs.plugins.kotlin) // Kotlin support
alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin alias(libs.plugins.intelliJPlatform) // IntelliJ Platform Gradle Plugin
alias(libs.plugins.changelog) // Gradle Changelog Plugin alias(libs.plugins.changelog) // Gradle Changelog Plugin
alias(libs.plugins.qodana) // Gradle Qodana Plugin alias(libs.plugins.qodana) // Gradle Qodana Plugin
alias(libs.plugins.kover) // Gradle Kover Plugin alias(libs.plugins.kover) // Gradle Kover Plugin
} }
group = properties("pluginGroup").get() group = providers.gradleProperty("pluginGroup").get()
version = properties("pluginVersion").get() version = providers.gradleProperty("pluginVersion").get()
// Set the JVM language level used to build the project.
kotlin {
jvmToolchain(21)
}
// Configure project's dependencies // Configure project's dependencies
repositories { repositories {
mavenCentral() mavenCentral()
// IntelliJ Platform Gradle Plugin Repositories Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-repositories-extension.html
intellijPlatform {
defaultRepositories()
}
} }
// Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog // Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog
dependencies { dependencies {
// implementation(libs.annotations)
implementation(libs.json5.java) implementation(libs.json5.java)
implementation(libs.commons.lang3) implementation(libs.commons.lang3)
implementation(libs.commons.text) implementation(libs.commons.text)
} testImplementation(libs.junit)
testImplementation(libs.opentest4j)
// Set the JVM language level used to build the project. // IntelliJ Platform Gradle Plugin Dependencies Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html
kotlin { intellijPlatform {
jvmToolchain(17) create(providers.gradleProperty("platformType"), providers.gradleProperty("platformVersion"))
}
// Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html // Plugin Dependencies. Uses `platformBundledPlugins` property from the gradle.properties file for bundled IntelliJ Platform plugins.
intellij { bundledPlugins(providers.gradleProperty("platformBundledPlugins").map { it.split(',') })
pluginName = properties("pluginName")
version = properties("platformVersion")
type = properties("platformType")
// Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file. // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file for plugin from JetBrains Marketplace.
plugins = properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) } plugins(providers.gradleProperty("platformPlugins").map { it.split(',') })
}
// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin // Module Dependencies. Uses `platformBundledModules` property from the gradle.properties file for bundled IntelliJ Platform modules.
changelog { bundledModules(providers.gradleProperty("platformBundledModules").map { it.split(',') })
groups.empty()
repositoryUrl = properties("pluginRepositoryUrl")
}
// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration testFramework(TestFrameworkType.Platform)
koverReport {
defaults {
xml {
onCheck = true
}
} }
} }
tasks { // Configure IntelliJ Platform Gradle Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html
wrapper { intellijPlatform {
gradleVersion = properties("gradleVersion").get() pluginConfiguration {
} name = providers.gradleProperty("pluginName")
version = providers.gradleProperty("pluginVersion")
patchPluginXml {
version = properties("pluginVersion")
sinceBuild = properties("pluginSinceBuild")
untilBuild = properties("pluginUntilBuild")
// Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest // Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
pluginDescription = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map { description = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
val start = "<!-- Plugin description -->" val start = "<!-- Plugin description -->"
val end = "<!-- Plugin description end -->" val end = "<!-- Plugin description end -->"
with (it.lines()) { with(it.lines()) {
if (!containsAll(listOf(start, end))) { if (!containsAll(listOf(start, end))) {
throw GradleException("Plugin description section not found in README.md:\n$start ... $end") throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
} }
@ -84,7 +75,7 @@ tasks {
val changelog = project.changelog // local variable for configuration cache compatibility val changelog = project.changelog // local variable for configuration cache compatibility
// Get the latest available change notes from the changelog file // Get the latest available change notes from the changelog file
changeNotes = properties("pluginVersion").map { pluginVersion -> changeNotes = providers.gradleProperty("pluginVersion").map { pluginVersion ->
with(changelog) { with(changelog) {
renderItem( renderItem(
(getOrNull(pluginVersion) ?: getUnreleased()) (getOrNull(pluginVersion) ?: getUnreleased())
@ -94,29 +85,77 @@ tasks {
) )
} }
} }
ideaVersion {
sinceBuild = providers.gradleProperty("pluginSinceBuild")
}
} }
// Configure UI tests plugin signing {
// Read more: https://github.com/JetBrains/intellij-ui-test-robot certificateChain = providers.environmentVariable("CERTIFICATE_CHAIN")
runIdeForUiTests { privateKey = providers.environmentVariable("PRIVATE_KEY")
systemProperty("robot-server.port", "8082") password = providers.environmentVariable("PRIVATE_KEY_PASSWORD")
systemProperty("ide.mac.message.dialogs.as.sheets", "false")
systemProperty("jb.privacy.policy.text", "<!--999.999-->")
systemProperty("jb.consents.confirmation.enabled", "false")
} }
signPlugin { publishing {
certificateChain = environment("CERTIFICATE_CHAIN") token = providers.environmentVariable("PUBLISH_TOKEN")
privateKey = environment("PRIVATE_KEY")
password = environment("PRIVATE_KEY_PASSWORD")
}
publishPlugin {
dependsOn("patchChangelog")
token = environment("PUBLISH_TOKEN")
// The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3 // The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
// Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more: // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
// https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
channels = properties("pluginVersion").map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) } channels = providers.gradleProperty("pluginVersion").map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) }
}
pluginVerification {
ides {
recommended()
}
}
}
// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
changelog {
groups.empty()
repositoryUrl = providers.gradleProperty("pluginRepositoryUrl")
}
// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration
kover {
reports {
total {
xml {
onCheck = true
}
}
}
}
tasks {
wrapper {
gradleVersion = providers.gradleProperty("gradleVersion").get()
}
publishPlugin {
dependsOn(patchChangelog)
}
}
intellijPlatformTesting {
runIde {
register("runIdeForUiTests") {
task {
jvmArgumentProviders += CommandLineArgumentProvider {
listOf(
"-Drobot-server.port=8082",
"-Dide.mac.message.dialogs.as.sheets=false",
"-Djb.privacy.policy.text=<!--999.999-->",
"-Djb.consents.confirmation.enabled=false",
)
}
}
plugins {
robotServerPlugin()
}
}
} }
} }

10
codecov.yml Normal file
View File

@ -0,0 +1,10 @@
coverage:
status:
project:
default:
informational: true
threshold: 0%
base: auto
patch:
default:
informational: true

View File

@ -4,22 +4,25 @@ pluginGroup = de.marhali.easyi18n
pluginName = easy-i18n pluginName = easy-i18n
pluginRepositoryUrl = https://github.com/marhali/easy-i18n pluginRepositoryUrl = https://github.com/marhali/easy-i18n
# SemVer format -> https://semver.org # SemVer format -> https://semver.org
pluginVersion = 4.5.1 pluginVersion = 4.9.0
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 223 pluginSinceBuild = 242
pluginUntilBuild = 241.*
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IU platformType = IU
platformVersion = 2022.3.3 platformVersion = 2025.1.5
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 # Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
platformPlugins = org.jetbrains.kotlin, JavaScript, com.jetbrains.php:223.8836.42 platformPlugins = com.jetbrains.php:242.23726.16
# Example: platformBundledPlugins = com.intellij.java
platformBundledPlugins = org.jetbrains.kotlin, JavaScript
# Example: platformBundledModules = intellij.spellchecker
platformBundledModules =
# Gradle Releases -> https://github.com/gradle/gradle/releases # Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 8.7 gradleVersion = 9.0.0
# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib # Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
kotlin.stdlib.default.dependency = false kotlin.stdlib.default.dependency = false

View File

@ -1,26 +1,28 @@
[versions] [versions]
# libraries # libraries
annotations = "24.1.0"
json5-java = "2.0.0" json5-java = "2.0.0"
commons-lang3 = "3.14.0" commons-lang3 = "3.18.0"
commons-text = "1.11.0" commons-text = "1.14.0"
junit = "4.13.2"
opentest4j = "1.3.0"
# plugins # plugins
kotlin = "1.9.23" changelog = "2.4.0"
changelog = "2.2.0" intelliJPlatform = "2.7.2"
gradleIntelliJPlugin = "1.17.2" kotlin = "2.2.0"
qodana = "2023.3.1" kover = "0.9.1"
kover = "0.7.6" qodana = "2025.1.1"
[libraries] [libraries]
annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" }
json5-java = { group = "de.marhali", name = "json5-java", version.ref = "json5-java" } json5-java = { group = "de.marhali", name = "json5-java", version.ref = "json5-java" }
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commons-lang3" } commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commons-lang3" }
commons-text = { group = "org.apache.commons", name = "commons-text", version.ref = "commons-text" } commons-text = { group = "org.apache.commons", name = "commons-text", version.ref = "commons-text" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
opentest4j = { group = "org.opentest4j", name = "opentest4j", version.ref = "opentest4j" }
[plugins] [plugins]
changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" } changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" }
gradleIntelliJPlugin = { id = "org.jetbrains.intellij", version.ref = "gradleIntelliJPlugin" } intelliJPlatform = { id = "org.jetbrains.intellij.platform", version.ref = "intelliJPlatform" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" } qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" }

Binary file not shown.

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

14
gradlew vendored
View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -112,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -203,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

6
gradlew.bat vendored
View File

@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@ -68,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@ -1,9 +1,9 @@
# Qodana configuration: # Qodana configuration:
# https://www.jetbrains.com/help/qodana/qodana-yaml.html # https://www.jetbrains.com/help/qodana/qodana-yaml.html
version: 1.0 version: "1.0"
linter: jetbrains/qodana-jvm-community:latest linter: jetbrains/qodana-jvm-community:2024.3
projectJDK: "17" projectJDK: "21"
profile: profile:
name: qodana.recommended name: qodana.recommended
exclude: exclude:

View File

@ -1,5 +1,5 @@
plugins { rootProject.name = "easy-i18n"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "easy-i18n" plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
}

View File

@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project;
import de.marhali.easyi18n.dialog.AddDialog; import de.marhali.easyi18n.dialog.AddDialog;
import de.marhali.easyi18n.model.KeyPath; import de.marhali.easyi18n.model.KeyPath;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import de.marhali.easyi18n.settings.ProjectSettingsService; import de.marhali.easyi18n.settings.ProjectSettingsService;
import de.marhali.easyi18n.util.DocumentUtil; import de.marhali.easyi18n.util.DocumentUtil;
@ -47,7 +48,7 @@ class LocalizeItAction extends AnAction {
throw new RuntimeException("Project is null!"); throw new RuntimeException("Project is null!");
} }
AddDialog dialog = new AddDialog(project, new KeyPath(text), text, (key) -> replaceSelectedText(project, editor, key)); AddDialog dialog = new AddDialog(project, new KeyPath(convertKeyToNamingCase(text, project)), text, (key) -> replaceSelectedText(project, editor, key));
dialog.showAndHandle(); dialog.showAndHandle();
} }
@ -55,8 +56,8 @@ class LocalizeItAction extends AnAction {
* Replaces the selected text in the editor with a new text generated from the provided key. * Replaces the selected text in the editor with a new text generated from the provided key.
* *
* @param project the project where the editor belongs * @param project the project where the editor belongs
* @param editor the editor where the text is selected * @param editor the editor where the text is selected
* @param key the key used to generate the replacement text * @param key the key used to generate the replacement text
*/ */
private void replaceSelectedText(Project project, @NotNull Editor editor, @NotNull String key) { private void replaceSelectedText(Project project, @NotNull Editor editor, @NotNull String key) {
int selectionStart = editor.getSelectionModel().getSelectionStart(); int selectionStart = editor.getSelectionModel().getSelectionStart();
@ -71,13 +72,24 @@ class LocalizeItAction extends AnAction {
* Builds a replacement string based on the provided flavor template, key, and document util. * Builds a replacement string based on the provided flavor template, key, and document util.
* *
* @param flavorTemplate the flavor template string * @param flavorTemplate the flavor template string
* @param key the key used to generate the replacement text * @param key the key used to generate the replacement text
* @param documentUtil the document util object used to determine the document type * @param documentUtil the document util object used to determine the document type
* @return the built replacement string * @return the built replacement string
*/ */
private String buildReplacement(String flavorTemplate, String key, DocumentUtil documentUtil) { private String buildReplacement(String flavorTemplate, String key, DocumentUtil documentUtil) {
if (documentUtil.isVue() || documentUtil.isJsOrTs()) return flavorTemplate + "('" + key + "')"; if (documentUtil.isVue() || documentUtil.isJsOrTs()) return flavorTemplate + "('" + key + "')";
return flavorTemplate + "(\"" + key + "\")"; return flavorTemplate + "(\"" + key + "\")";
} }
/**
* Converts a given key to the specified naming convention.
*
* @param key the key to convert
* @param project the project where the key is being converted
* @return the converted key
*/
private String convertKeyToNamingCase(String key, Project project) {
return NamingConvention.convertKeyToConvention(key, ProjectSettingsService.get(project).getState().getCaseFormat());
}
} }

View File

@ -0,0 +1,17 @@
package de.marhali.easyi18n.assistance.completion;
import com.intellij.codeInsight.completion.CompletionContributor;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl;
/**
* Xml specific completion contributor.
* @author adeptius
*/
public class XmlCompletionContributor extends CompletionContributor {
public XmlCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement().inside(XmlAttributeValueImpl.class),
new KeyCompletionProvider());
}
}

View File

@ -49,7 +49,7 @@ abstract class AbstractFoldingBuilder extends FoldingBuilderEx implements Option
public FoldingDescriptor @NotNull [] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) { public FoldingDescriptor @NotNull [] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
if(quick || !isAssistance(root.getProject())) { if(quick || !isAssistance(root.getProject())) {
return FoldingDescriptor.EMPTY; return FoldingDescriptor.EMPTY_ARRAY;
} }
List<FoldingDescriptor> descriptors = new ArrayList<>(); List<FoldingDescriptor> descriptors = new ArrayList<>();

View File

@ -0,0 +1,27 @@
package de.marhali.easyi18n.assistance.intention;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttributeValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Xml specific translation key intention.
* @author adeptius
*/
public class XmlTranslationIntention extends AbstractTranslationIntention {
@Override
protected @Nullable String extractText(@NotNull PsiElement element) {
if(!(element.getParent() instanceof XmlAttributeValue)) {
return null;
}
return ((XmlAttributeValue) element.getParent()).getValue();
}
@Override
@NotNull TextRange convertRange(@NotNull TextRange input) {
return new TextRange(input.getStartOffset() + 1, input.getEndOffset() - 1);
}
}

View File

@ -0,0 +1,38 @@
package de.marhali.easyi18n.assistance.reference;
import com.intellij.openapi.project.Project;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.PsiReferenceRegistrar;
import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
/**
* Xml specific key reference binding
* @author adeptius
*/
public class XmlKeyReferenceContributor extends AbstractKeyReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(
PlatformPatterns.psiElement(XmlAttributeValueImpl.class),
getProvider());
}
private PsiReferenceProvider getProvider() {
return new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(
@NotNull PsiElement element, @NotNull ProcessingContext context) {
Project project = element.getProject();
XmlAttributeValueImpl literalExpression = (XmlAttributeValueImpl) element;
String value = literalExpression.getValue();
return getReferences(project, element, value);
}
};
}
}

View File

@ -3,6 +3,7 @@ package de.marhali.easyi18n.dialog;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextArea;
import com.intellij.ui.components.JBTextField; import com.intellij.ui.components.JBTextField;
import com.intellij.util.Consumer; import com.intellij.util.Consumer;
import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.FormBuilder;
@ -38,7 +39,7 @@ abstract class TranslationDialog extends DialogWrapper {
protected final @NotNull Translation origin; protected final @NotNull Translation origin;
protected final JTextField keyField; protected final JTextField keyField;
protected final Map<String, JTextField> localeValueFields; protected final Map<String, JTextArea> localeValueFields;
private final Set<Consumer<TranslationUpdate>> callbacks; private final Set<Consumer<TranslationUpdate>> callbacks;
@ -64,7 +65,12 @@ abstract class TranslationDialog extends DialogWrapper {
this.localeValueFields = new HashMap<>(); this.localeValueFields = new HashMap<>();
for(String locale : InstanceManager.get(project).store().getData().getLocales()) { for(String locale : InstanceManager.get(project).store().getData().getLocales()) {
localeValueFields.put(locale, new JBTextField(value != null ? value.get(locale) : null)); var field = new JBTextArea(value != null ? value.get(locale) : null, 1, 1);
field.setLineWrap(true);
field.setWrapStyleWord(true);
field.setBorder(BorderFactory.createTitledBorder(locale));
localeValueFields.put(locale, field);
} }
} }
@ -114,7 +120,7 @@ abstract class TranslationDialog extends DialogWrapper {
TranslationValue value = new TranslationValue(); TranslationValue value = new TranslationValue();
for(Map.Entry<String, JTextField> entry : localeValueFields.entrySet()) { for(Map.Entry<String, JTextArea> entry : localeValueFields.entrySet()) {
value.put(entry.getKey(), entry.getValue().getText()); value.put(entry.getKey(), entry.getValue().getText());
} }
@ -136,8 +142,8 @@ abstract class TranslationDialog extends DialogWrapper {
private JComponent createLocalesPanel() { private JComponent createLocalesPanel() {
FormBuilder builder = FormBuilder.createFormBuilder(); FormBuilder builder = FormBuilder.createFormBuilder();
for(Map.Entry<String, JTextField> localeEntry : localeValueFields.entrySet()) { for(Map.Entry<String, JTextArea> localeEntry : localeValueFields.entrySet()) {
builder.addLabeledComponent(localeEntry.getKey(), localeEntry.getValue(), 6, true); builder.addComponent(localeEntry.getValue(), 6);
} }
JScrollPane scrollPane = new JBScrollPane(builder.getPanel()); JScrollPane scrollPane = new JBScrollPane(builder.getPanel());

View File

@ -3,35 +3,61 @@ package de.marhali.easyi18n.settings;
import de.marhali.easyi18n.io.parser.ParserStrategyType; import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.io.folder.FolderStrategyType; import de.marhali.easyi18n.io.folder.FolderStrategyType;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* API to access the project-specific configuration for this plugin. * API to access the project-specific configuration for this plugin.
*
* @author marhaliu * @author marhaliu
*/ */
public interface ProjectSettings { public interface ProjectSettings {
// Resource Configuration // Resource Configuration
@Nullable String getLocalesDirectory(); @Nullable
@NotNull FolderStrategyType getFolderStrategy(); String getLocalesDirectory();
@NotNull ParserStrategyType getParserStrategy();
@NotNull String getFilePattern(); @NotNull
FolderStrategyType getFolderStrategy();
@NotNull
ParserStrategyType getParserStrategy();
@NotNull
String getFilePattern();
boolean isIncludeSubDirs(); boolean isIncludeSubDirs();
boolean isSorting(); boolean isSorting();
// Editor Configuration // Editor Configuration
@Nullable String getNamespaceDelimiter(); @Nullable
@NotNull String getSectionDelimiter(); String getNamespaceDelimiter();
@Nullable String getContextDelimiter();
@Nullable String getPluralDelimiter(); @NotNull
@Nullable String getDefaultNamespace(); String getSectionDelimiter();
@NotNull String getPreviewLocale();
@Nullable
String getContextDelimiter();
@Nullable
String getPluralDelimiter();
@Nullable
String getDefaultNamespace();
@NotNull
String getPreviewLocale();
boolean isNestedKeys(); boolean isNestedKeys();
boolean isAssistance(); boolean isAssistance();
// Experimental Configuration // Experimental Configuration
boolean isAlwaysFold(); boolean isAlwaysFold();
String getFlavorTemplate(); String getFlavorTemplate();
@NotNull
NamingConvention getCaseFormat();
} }

View File

@ -13,6 +13,7 @@ import com.intellij.util.ui.FormBuilder;
import de.marhali.easyi18n.io.parser.ArrayMapper; import de.marhali.easyi18n.io.parser.ArrayMapper;
import de.marhali.easyi18n.io.parser.ParserStrategyType; import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import de.marhali.easyi18n.settings.presets.Preset; import de.marhali.easyi18n.settings.presets.Preset;
import javax.swing.*; import javax.swing.*;
@ -26,6 +27,7 @@ import java.util.ResourceBundle;
/** /**
* Configuration panel with all possible options for this plugin. * Configuration panel with all possible options for this plugin.
*
* @author marhali * @author marhali
*/ */
public class ProjectSettingsComponent extends ProjectSettingsComponentState { public class ProjectSettingsComponent extends ProjectSettingsComponentState {
@ -64,7 +66,9 @@ public class ProjectSettingsComponent extends ProjectSettingsComponentState {
.addVerticalGap(24) .addVerticalGap(24)
.addComponent(new TitledSeparator(bundle.getString("settings.experimental.title"))) .addComponent(new TitledSeparator(bundle.getString("settings.experimental.title")))
.addComponent(constructAlwaysFoldField()) .addComponent(constructAlwaysFoldField())
.addVerticalGap(12)
.addLabeledComponent(bundle.getString("settings.experimental.flavor-template"), constructFlavorTemplate(), 1, false) .addLabeledComponent(bundle.getString("settings.experimental.flavor-template"), constructFlavorTemplate(), 1, false)
.addLabeledComponent(bundle.getString("settings.experimental.key-naming-format.title"), constructKeyCaseFormater(), 1, false)
.addComponentFillVertically(new JPanel(), 0) .addComponentFillVertically(new JPanel(), 0)
.getPanel(); .getPanel();
} }
@ -226,6 +230,14 @@ public class ProjectSettingsComponent extends ProjectSettingsComponentState {
return flavorTemplate; return flavorTemplate;
} }
private JComponent constructKeyCaseFormater() {
KeyCaseFormater = new ComboBox<>(NamingConvention.getEnumNames());
KeyCaseFormater.setToolTipText(bundle.getString("settings.experimental.key-naming-format.tooltip"));
KeyCaseFormater.setMinimumAndPreferredWidth(200);
return KeyCaseFormater;
}
private ItemListener handleParserChange() { private ItemListener handleParserChange() {
return e -> { return e -> {
if (e.getStateChange() == ItemEvent.SELECTED) { if (e.getStateChange() == ItemEvent.SELECTED) {

View File

@ -5,12 +5,14 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import de.marhali.easyi18n.io.parser.ParserStrategyType; import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.io.folder.FolderStrategyType; import de.marhali.easyi18n.io.folder.FolderStrategyType;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import de.marhali.easyi18n.settings.presets.Preset; import de.marhali.easyi18n.settings.presets.Preset;
import javax.swing.*; import javax.swing.*;
/** /**
* Mandatory for state management for the project settings component. * Mandatory for state management for the project settings component.
*
* @author marhali * @author marhali
*/ */
public class ProjectSettingsComponentState { public class ProjectSettingsComponentState {
@ -41,6 +43,7 @@ public class ProjectSettingsComponentState {
protected JCheckBox alwaysFold; protected JCheckBox alwaysFold;
protected JTextField flavorTemplate; protected JTextField flavorTemplate;
protected ComboBox<String> KeyCaseFormater;
protected ProjectSettingsState getState() { protected ProjectSettingsState getState() {
// Every field needs to provide its state // Every field needs to provide its state
@ -65,8 +68,11 @@ public class ProjectSettingsComponentState {
state.setAssistance(assistance.isSelected()); state.setAssistance(assistance.isSelected());
state.setAlwaysFold(alwaysFold.isSelected()); state.setAlwaysFold(alwaysFold.isSelected());
state.setFlavorTemplate(flavorTemplate.getText()); state.setFlavorTemplate(flavorTemplate.getText());
state.setCaseFormat(NamingConvention.fromString(KeyCaseFormater.getSelectedItem().toString()));
return state; return state;
} }
@ -92,5 +98,7 @@ public class ProjectSettingsComponentState {
alwaysFold.setSelected(state.isAlwaysFold()); alwaysFold.setSelected(state.isAlwaysFold());
flavorTemplate.setText(state.getFlavorTemplate()); flavorTemplate.setText(state.getFlavorTemplate());
KeyCaseFormater.setSelectedItem(state.getCaseFormat().getName());
} }
} }

View File

@ -6,6 +6,7 @@ import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.io.folder.FolderStrategyType; import de.marhali.easyi18n.io.folder.FolderStrategyType;
import de.marhali.easyi18n.settings.presets.DefaultPreset; import de.marhali.easyi18n.settings.presets.DefaultPreset;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -13,32 +14,48 @@ import java.util.Objects;
/** /**
* Represents the project-specific configuration of this plugin. * Represents the project-specific configuration of this plugin.
*
* @author marhali * @author marhali
*/ */
public class ProjectSettingsState implements ProjectSettings { public class ProjectSettingsState implements ProjectSettings {
// Resource Configuration // Resource Configuration
@Property private String localesDirectory; @Property
@Property private FolderStrategyType folderStrategy; private String localesDirectory;
@Property private ParserStrategyType parserStrategy; @Property
@Property private String filePattern; private FolderStrategyType folderStrategy;
@Property
private ParserStrategyType parserStrategy;
@Property
private String filePattern;
@Property private Boolean includeSubDirs; @Property
@Property private boolean sorting; private Boolean includeSubDirs;
@Property
private boolean sorting;
// Editor configuration // Editor configuration
@Property private String namespaceDelimiter; @Property
@Property private String sectionDelimiter; private String namespaceDelimiter;
@Property private String contextDelimiter; @Property
@Property private String pluralDelimiter; private String sectionDelimiter;
@Property private String defaultNamespace; @Property
@Property private String previewLocale; private String contextDelimiter;
@Property
private String pluralDelimiter;
@Property
private String defaultNamespace;
@Property
private String previewLocale;
@Property private Boolean nestedKeys; @Property
@Property private Boolean assistance; private Boolean nestedKeys;
@Property
private Boolean assistance;
// Experimental configuration // Experimental configuration
@Property private Boolean alwaysFold; @Property
private Boolean alwaysFold;
/** /**
* The `flavorTemplate` specifies the format used for replacing strings with their i18n (internationalization) counterparts. * The `flavorTemplate` specifies the format used for replacing strings with their i18n (internationalization) counterparts.
@ -47,7 +64,11 @@ public class ProjectSettingsState implements ProjectSettings {
* the specific framework or developers' preferences for handling i18n. The ability to dynamically change this template adds flexibility and customization * the specific framework or developers' preferences for handling i18n. The ability to dynamically change this template adds flexibility and customization
* to cater to different i18n handling methods. * to cater to different i18n handling methods.
*/ */
@Property private String flavorTemplate; @Property
private String flavorTemplate;
@Property
private NamingConvention caseFormat;
public ProjectSettingsState() { public ProjectSettingsState() {
this(new DefaultPreset()); this(new DefaultPreset());
@ -75,6 +96,7 @@ public class ProjectSettingsState implements ProjectSettings {
this.alwaysFold = defaults.isAlwaysFold(); this.alwaysFold = defaults.isAlwaysFold();
this.flavorTemplate = defaults.getFlavorTemplate(); this.flavorTemplate = defaults.getFlavorTemplate();
this.caseFormat = defaults.getCaseFormat();
} }
@Override @Override
@ -158,6 +180,11 @@ public class ProjectSettingsState implements ProjectSettings {
return this.flavorTemplate; return this.flavorTemplate;
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return this.caseFormat;
}
public void setLocalesDirectory(String localesDirectory) { public void setLocalesDirectory(String localesDirectory) {
this.localesDirectory = localesDirectory; this.localesDirectory = localesDirectory;
} }
@ -218,10 +245,15 @@ public class ProjectSettingsState implements ProjectSettings {
this.alwaysFold = alwaysFold; this.alwaysFold = alwaysFold;
} }
public void setFlavorTemplate(String flavorTemplate){ public void setFlavorTemplate(String flavorTemplate) {
this.flavorTemplate = flavorTemplate; this.flavorTemplate = flavorTemplate;
} }
public void setCaseFormat(NamingConvention caseFormat) {
this.caseFormat = caseFormat;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -242,7 +274,8 @@ public class ProjectSettingsState implements ProjectSettings {
&& Objects.equals(nestedKeys, that.nestedKeys) && Objects.equals(nestedKeys, that.nestedKeys)
&& Objects.equals(assistance, that.assistance) && Objects.equals(assistance, that.assistance)
&& Objects.equals(alwaysFold, that.alwaysFold) && Objects.equals(alwaysFold, that.alwaysFold)
&& Objects.equals(flavorTemplate,that.flavorTemplate); && Objects.equals(flavorTemplate, that.flavorTemplate)
&& Objects.equals(caseFormat, that.caseFormat);
} }
@Override @Override
@ -250,7 +283,7 @@ public class ProjectSettingsState implements ProjectSettings {
return Objects.hash( return Objects.hash(
localesDirectory, folderStrategy, parserStrategy, filePattern, includeSubDirs, localesDirectory, folderStrategy, parserStrategy, filePattern, includeSubDirs,
sorting, namespaceDelimiter, sectionDelimiter, contextDelimiter, pluralDelimiter, sorting, namespaceDelimiter, sectionDelimiter, contextDelimiter, pluralDelimiter,
defaultNamespace, previewLocale, nestedKeys, assistance, alwaysFold,flavorTemplate defaultNamespace, previewLocale, nestedKeys, assistance, alwaysFold, flavorTemplate, caseFormat
); );
} }
@ -273,6 +306,7 @@ public class ProjectSettingsState implements ProjectSettings {
", assistance=" + assistance + ", assistance=" + assistance +
", alwaysFold=" + alwaysFold + ", alwaysFold=" + alwaysFold +
", flavorTemplate=" + flavorTemplate + ", flavorTemplate=" + flavorTemplate +
", caseFormat=" + caseFormat.toString() +
'}'; '}';
} }
} }

View File

@ -91,4 +91,9 @@ public class DefaultPreset implements ProjectSettings {
public String getFlavorTemplate() { public String getFlavorTemplate() {
return "$i18n.t"; return "$i18n.t";
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
}
} }

View File

@ -0,0 +1,92 @@
package de.marhali.easyi18n.settings.presets;
import com.google.common.base.CaseFormat;
import java.util.Arrays;
/**
* Enum representing different naming conventions.
* Provides utility methods to convert keys to the specified convention.
*/
public enum NamingConvention {
CAMEL_CASE("Camel Case"),
PASCAL_CASE("Pascal Case"),
SNAKE_CASE("Snake Case"),
SNAKE_CASE_UPPERCASE("Snake Case (Uppercase)");
private final String name;
private NamingConvention(String name) {
this.name = name;
}
/**
* Retrieves the name of the current instance of the class.
*
* @return the name of the current instance
*/
public String getName() {
return this.name;
}
@Override
public String toString() {
return super.name().toLowerCase();
}
/**
* Converts a string representation of a naming convention to the corresponding NamingConvention enum value.
*
* @param name the string representation of the naming convention
* @return the corresponding NamingConvention enum value
*/
static public NamingConvention fromString(String name) {
for (NamingConvention value : NamingConvention.values()) {
if (value.getName().equals(name))
return value;
}
return NamingConvention.CAMEL_CASE;
}
/**
* Returns an array of strings representing the names of the enum values in the {@link NamingConvention} enum.
*
* @return an array of strings representing the enum names
*/
static public String[] getEnumNames() {
return Arrays.stream(NamingConvention.values())
.map(NamingConvention::getName)
.toArray(String[]::new);
}
/**
* Converts a given key to the specified naming convention.
*
* @param key the key to convert
* @param convention the naming convention to convert the key to
* @return the converted key
*/
static public String convertKeyToConvention(String key, NamingConvention convention) {
String newKey = key.toLowerCase();
newKey = newKey.replaceAll("\\s+", "_");
return switch (convention) {
case SNAKE_CASE:
yield formatToSnakeCase(newKey, false);
case SNAKE_CASE_UPPERCASE:
yield formatToSnakeCase(newKey, true);
case CAMEL_CASE:
yield formatToCamelCase(newKey, false);
case PASCAL_CASE:
yield formatToCamelCase(newKey, true);
};
}
static private String formatToCamelCase(String key, boolean capitalized) {
return CaseFormat.LOWER_UNDERSCORE.to(capitalized ? CaseFormat.UPPER_CAMEL : CaseFormat.LOWER_CAMEL, key);
}
static private String formatToSnakeCase(String key, boolean capitalized) {
return CaseFormat.LOWER_UNDERSCORE.to(capitalized ? CaseFormat.UPPER_UNDERSCORE : CaseFormat.LOWER_UNDERSCORE, key);
}
}

View File

@ -91,4 +91,8 @@ public class ReactI18NextPreset implements ProjectSettings {
public String getFlavorTemplate() { public String getFlavorTemplate() {
return "$i18n.t"; return "$i18n.t";
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
}
} }

View File

@ -90,4 +90,9 @@ public class VueI18nPreset implements ProjectSettings {
public String getFlavorTemplate() { public String getFlavorTemplate() {
return "$i18n.t"; return "$i18n.t";
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
}
} }

View File

@ -1,5 +1,11 @@
<idea-plugin> <idea-plugin>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<psi.referenceContributor
language="HTML"
implementation="de.marhali.easyi18n.assistance.reference.XmlKeyReferenceContributor"
/>
<lang.foldingBuilder <lang.foldingBuilder
language="HTML" language="HTML"
implementationClass="de.marhali.easyi18n.assistance.folding.XmlFoldingBuilder" implementationClass="de.marhali.easyi18n.assistance.folding.XmlFoldingBuilder"
@ -9,5 +15,14 @@
language="HTML" language="HTML"
implementationClass="de.marhali.easyi18n.assistance.documentation.CommonDocumentationProvider" implementationClass="de.marhali.easyi18n.assistance.documentation.CommonDocumentationProvider"
/> />
<completion.contributor
language="HTML"
implementationClass="de.marhali.easyi18n.assistance.completion.XmlCompletionContributor"
/>
<intentionAction>
<className>de.marhali.easyi18n.assistance.intention.XmlTranslationIntention</className>
</intentionAction>
</extensions> </extensions>
</idea-plugin> </idea-plugin>

View File

@ -62,6 +62,9 @@ settings.experimental.always-fold.title=Always fold translation keys
settings.experimental.always-fold.tooltip=Forces the editor to always display the value behind a translation key. The value cannot be unfolded when this function is active. settings.experimental.always-fold.tooltip=Forces the editor to always display the value behind a translation key. The value cannot be unfolded when this function is active.
settings.experimental.flavor-template =I18n flavor template settings.experimental.flavor-template =I18n flavor template
settings.experimental.flavor-template-tooltip = Specify how to replace strings with i18n representation. settings.experimental.flavor-template-tooltip = Specify how to replace strings with i18n representation.
settings.experimental.key-naming-format.title=Key format of extracted translation
settings.experimental.key-naming-format.tooltip=Choose Naming Convention for the keys of extracted translation
error.io=An error occurred while processing translation files. \n\ error.io=An error occurred while processing translation files. \n\
Config: {0} => {1} ({2}) \n\ Config: {0} => {1} ({2}) \n\
Path: {3} \n\ Path: {3} \n\

View File

@ -3,6 +3,7 @@ package de.marhali.easyi18n;
import de.marhali.easyi18n.io.parser.ParserStrategyType; import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.io.folder.FolderStrategyType; import de.marhali.easyi18n.io.folder.FolderStrategyType;
import de.marhali.easyi18n.model.KeyPath; import de.marhali.easyi18n.model.KeyPath;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import de.marhali.easyi18n.settings.ProjectSettings; import de.marhali.easyi18n.settings.ProjectSettings;
import de.marhali.easyi18n.util.KeyPathConverter; import de.marhali.easyi18n.util.KeyPathConverter;
@ -172,6 +173,11 @@ public class KeyPathConverterTest {
public boolean isIncludeSubDirs() { public boolean isIncludeSubDirs() {
return false; return false;
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
}
}); });
} }
} }

View File

@ -22,6 +22,7 @@ import java.util.Objects;
/** /**
* End-to-end test case. * End-to-end test case.
*
* @author marhali * @author marhali
*/ */
public abstract class EndToEndTestCase extends BasePlatformTestCase { public abstract class EndToEndTestCase extends BasePlatformTestCase {
@ -57,7 +58,8 @@ public abstract class EndToEndTestCase extends BasePlatformTestCase {
out.setLocalesDirectory(tempPath.toString()); out.setLocalesDirectory(tempPath.toString());
ProjectSettingsService.get(getProject()).setState(out); ProjectSettingsService.get(getProject()).setState(out);
InstanceManager.get(getProject()).store().saveToPersistenceLayer(success -> {}); InstanceManager.get(getProject()).store().saveToPersistenceLayer(success -> {
});
// Compare file structure and contents // Compare file structure and contents
IOFileFilter fileFilter = TrueFileFilter.INSTANCE; IOFileFilter fileFilter = TrueFileFilter.INSTANCE;
@ -73,7 +75,7 @@ public abstract class EndToEndTestCase extends BasePlatformTestCase {
assertEquals(originalFiles.length, outputFiles.length); assertEquals(originalFiles.length, outputFiles.length);
for(int i = 0; i < originalFiles.length; i++) { for (int i = 0; i < originalFiles.length; i++) {
File originalFile = originalFiles[i]; File originalFile = originalFiles[i];
File outputFile = outputFiles[i]; File outputFile = outputFiles[i];
@ -82,4 +84,4 @@ public abstract class EndToEndTestCase extends BasePlatformTestCase {
FileUtils.readFileToString(outputFile, CHARSET)); FileUtils.readFileToString(outputFile, CHARSET));
} }
} }
} }

View File

@ -7,6 +7,7 @@ import de.marhali.easyi18n.io.parser.properties.PropertiesMapper;
import de.marhali.easyi18n.io.parser.properties.SortableProperties; import de.marhali.easyi18n.io.parser.properties.SortableProperties;
import de.marhali.easyi18n.model.TranslationData; import de.marhali.easyi18n.model.TranslationData;
import de.marhali.easyi18n.model.KeyPath; import de.marhali.easyi18n.model.KeyPath;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import de.marhali.easyi18n.settings.ProjectSettings; import de.marhali.easyi18n.settings.ProjectSettings;
import de.marhali.easyi18n.util.KeyPathConverter; import de.marhali.easyi18n.util.KeyPathConverter;
@ -19,6 +20,7 @@ import java.util.*;
/** /**
* Unit tests for {@link PropertiesMapper}. * Unit tests for {@link PropertiesMapper}.
*
* @author marhali * @author marhali
*/ */
public class PropertiesMapperTest extends AbstractMapperTest { public class PropertiesMapperTest extends AbstractMapperTest {
@ -245,6 +247,11 @@ public class PropertiesMapperTest extends AbstractMapperTest {
public boolean isIncludeSubDirs() { public boolean isIncludeSubDirs() {
return false; return false;
} }
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
}
}); });
} }
} }

View File

@ -0,0 +1,35 @@
package de.marhali.easyi18n.settings;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import java.io.IOException;
public class NamingConventionTest extends BasePlatformTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
}
public void testConvertToNamingConvention() throws IOException {
assertEquals("helloWorld", NamingConvention.convertKeyToConvention("Hello World", NamingConvention.CAMEL_CASE));
assertEquals("hello_world", NamingConvention.convertKeyToConvention("Hello World", NamingConvention.SNAKE_CASE));
assertEquals("HelloWorld", NamingConvention.convertKeyToConvention("Hello World", NamingConvention.PASCAL_CASE));
assertEquals("HELLO_WORLD", NamingConvention.convertKeyToConvention("Hello World", NamingConvention.SNAKE_CASE_UPPERCASE));
}
public void testGetEnumNames() throws Exception {
String[] expected = {"Camel Case", "Pascal Case", "Snake Case", "Snake Case (Uppercase)"};
String[] actual = NamingConvention.getEnumNames();
assertEquals(expected.length, actual.length);
}
public void testFromString() {
assertEquals(NamingConvention.CAMEL_CASE, NamingConvention.fromString("Camel Case"));
assertEquals(NamingConvention.PASCAL_CASE, NamingConvention.fromString("Pascal Case"));
assertEquals(NamingConvention.SNAKE_CASE, NamingConvention.fromString("Snake Case"));
assertEquals(NamingConvention.SNAKE_CASE_UPPERCASE, NamingConvention.fromString("Snake Case (Uppercase)"));
assertEquals(NamingConvention.CAMEL_CASE, NamingConvention.fromString("Invalid Input"));
}
}

View File

@ -4,9 +4,11 @@ import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.XmlSerializerUtil;
import de.marhali.easyi18n.settings.presets.DefaultPreset; import de.marhali.easyi18n.settings.presets.DefaultPreset;
import de.marhali.easyi18n.settings.presets.NamingConvention;
/** /**
* Tests for the project settings service itself. * Tests for the project settings service itself.
*
* @author marhali * @author marhali
*/ */
public class ProjectSettingsServiceTest extends BasePlatformTestCase { public class ProjectSettingsServiceTest extends BasePlatformTestCase {
@ -35,4 +37,12 @@ public class ProjectSettingsServiceTest extends BasePlatformTestCase {
ProjectSettingsState after = XmlSerializerUtil.createCopy(previous); ProjectSettingsState after = XmlSerializerUtil.createCopy(previous);
assertEquals("mySinglePropTest", after.getLocalesDirectory()); assertEquals("mySinglePropTest", after.getLocalesDirectory());
} }
public void testPersistenceFormatCase() {
ProjectSettingsState previous = new ProjectSettingsState();
assertEquals(previous.getCaseFormat(), NamingConvention.CAMEL_CASE);
previous.setCaseFormat(NamingConvention.SNAKE_CASE);
ProjectSettingsState after = XmlSerializerUtil.createCopy(previous);
assertEquals(after.getCaseFormat(), NamingConvention.SNAKE_CASE);
}
} }

View File

@ -3,11 +3,13 @@ package de.marhali.easyi18n.settings;
import de.marhali.easyi18n.io.folder.FolderStrategyType; import de.marhali.easyi18n.io.folder.FolderStrategyType;
import de.marhali.easyi18n.io.parser.ParserStrategyType; import de.marhali.easyi18n.io.parser.ParserStrategyType;
import de.marhali.easyi18n.settings.presets.NamingConvention;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* Settings preset to test the functionality of the settings service. * Settings preset to test the functionality of the settings service.
*
* @author marhali * @author marhali
*/ */
public class SettingsTestPreset implements ProjectSettings { public class SettingsTestPreset implements ProjectSettings {
@ -88,6 +90,11 @@ public class SettingsTestPreset implements ProjectSettings {
@Override @Override
public String getFlavorTemplate() { public String getFlavorTemplate() {
return ""; return "t";
}
@Override
public @NotNull NamingConvention getCaseFormat() {
return NamingConvention.CAMEL_CASE;
} }
} }