Skip to content

SeijinD/StringSmith

Repository files navigation

StringSmith - Android Strings Toolkit

Stop hand-editing strings.xml. Extract hardcoded literals, kill duplicates, and find dead resources — all from the editor.

Build License Version Downloads Rating

IntelliJ IDEA / Android Studio plugin for managing Android strings.xml resources: extract hardcoded literals with context-aware replacement, detect duplicate values, and flag unused entries — without leaving the editor.

Contents

Features

Extract

  • Context-aware replacement
    • Inside @ComposablestringResource(R.string.key)
    • Inside composable entry-point lambdas (setContent, composable, navigation, dialog, bottomSheet, composed) and nested layout lambdas → stringResource(R.string.key)
    • Inside Activity / Fragment / ViewgetString(R.string.key)
    • Other Kotlin code → R.string.key
    • XML layout attribute → @string/key
  • Kotlin Multiplatform / Compose Multiplatform — targets under composeResources/values/ produce CMP references with auto-imported generated Res:
    • @ComposablestringResource(Res.string.key)
    • Other Kotlin code → Res.string.key
    • Res package auto-detected (gradle packageOfResClass → existing imports → derived), with a manual override in settings
  • Auto-import for Compose stringResource (sorted with existing imports)
  • Duplicate value detection during extract — reuse existing key
  • Multi-locale propagation across values-* folders
  • Kotlin template expressions extracted as %1$s format args (e.g. "Hello $name"stringResource(R.string.hello_s, name))
  • Quick-fix intention on hardcoded literals (Alt+Enter)
  • Quick extract: skip dialog when target is unambiguous (inline hint confirms the chosen key)
  • Batch extract: extract all strings in a file in one pass — colour-coded per-row status with per-status counts, a one-click Fix collisions action, and status/summary updating live while you edit keys
  • @Preview composables excluded by default (configurable)
  • Key suggestions romanize Greek and Cyrillic and strip Latin accents (Καλημέραkalimera, Cafécafe)

Duplicate

  • Copy an existing string resource to a new key across res/values/strings.xml and every values-* locale in one undoable step (Ctrl+Alt+D or Alt+Enter)
  • Works on any reference: R.string.key, Res.string.key, @string/key, or a <string> entry
  • Reuses each locale's existing translation; locales that don't translate the source key are skipped (shown in the dialog) instead of being filled with the default value
  • Optionally redirects the reference under the caret to the new key (Compose Multiplatform imports updated automatically)
  • Redirecting the reference shows an inline hint with the new key

Edit

  • Rename an existing string key and edit its default and per-locale values in one undoable step (Ctrl+Alt+E or Alt+Enter)
  • Renames every R.string.key, Res.string.key, and @string/key reference to the renamed key, scoped to the declaring module and its dependents
  • Reports how many references were updated (and warns when none were found, e.g. a dynamically-built key)
  • Works on any reference or a <string> entry, in Android and Compose Multiplatform projects

Inspect

  • Hardcoded string highlight in editor (opt-in) — Android resource XML (res/<type>/) and Kotlin only
  • Duplicate value in strings.xml (same text, different keys)
  • Unused string resource (no R.string.key, Res.string.key, or @string/key references)

Settings

Configurable prefix, naming convention, replacement style per context, locale propagation defaults, format-arg detection, inspection toggles, exclusion patterns, and custom composable wrapper names. A live key preview reflects your settings as you type a sample string. Compose Multiplatform projects can set a generated Res package override under Kotlin Multiplatform.

Custom wrappers: if your project wraps content in a helper whose trailing lambda is a @Composable scope (e.g. screenViewComposable { … }), add its name under Settings → Tools → StringSmith → Custom Composable Wrappers so strings inside it use stringResource.

Screenshots

Quick-fix (Alt+Enter)

Extract to strings.xml right on the hardcoded literal, with a context-aware replacement table and a Before/After preview.

Extract to strings.xml quick-fix with description popup

Extract dialog

Pick key, target module, and per-locale values — with live duplicate-key reuse and a context-aware replacement preview.

Extract dialog

Batch extract

Extract every string in a file in one pass — per-row keys, inclusion toggles, colour-coded status (New / Reuse existing / Duplicate / Collision / Invalid) that updates live as you edit keys, shared locale propagation, single undoable write.

Batch Extract Strings dialog

Duplicate

Copy an existing string resource to a new key across res/values/strings.xml and every locale in one undoable step — with a live preview and the option to redirect the reference under the caret. Works in Android and Compose Multiplatform (Res.string.key) projects alike.

Duplicate String Resource dialog

Inspections

Duplicate and unused strings.xml entries are flagged inline.

Inspections

Settings

Configure key generation, replacement style, locale defaults, format-arg detection, inspections, and strings.xml behavior.

Settings — key generation, replacement, locales, previews Settings — format strings, inspections, target module, behavior

Install

From JetBrains Marketplace

Install StringSmith

Or: Settings → Plugins → Marketplace, search StringSmith, install.

From source

git clone https://github.com/SeijinD/stringsmith.git
cd stringsmith
./gradlew buildPlugin

Output: build/distributions/stringsmith-<version>.zip

Install via Settings → Plugins → ⚙ → Install Plugin from Disk.

Run sandbox

./gradlew runIde              # default IntelliJ Platform sandbox
./gradlew runAndroidStudio    # Android Studio sandbox

Android Studio path is auto-detected per OS. Override via the androidStudioPath Gradle property (e.g. in ~/.gradle/gradle.properties) if installed elsewhere (such as a JetBrains Toolbox location).

Usage

Single extract (with dialog)

  1. Place caret inside a hardcoded string literal or XML attribute value.
  2. Ctrl+Alt+X or right-click → Extract to strings.xml.
  3. Pick key, module, locale rows in the dialog.
  4. Entry written to res/values/strings.xml; literal replaced with context-appropriate reference.

Quick extract (no dialog)

Ctrl+Alt+Shift+X — extracts immediately when the target is unambiguous (single module, no key collision, no locale variants, no existing key for the value). Falls back to the regular dialog otherwise.

Batch extract (whole file)

Ctrl+Alt+Shift+B or Refactor → Batch Extract Strings in File — opens a table of all extractable strings in the current file. Edit per-row keys, toggle inclusion, pick locale propagation, write all in one undoable step.

Duplicate a string resource

  1. Place caret on a string reference (R.string.key, Res.string.key, @string/key) or a <string> entry in strings.xml.
  2. Ctrl+Alt+D or right-click → Duplicate String Resource (also Alt+Enter).
  3. Pick the new key. The dialog lists which locales receive the copy. Optionally redirect the reference under the caret to the new key.

Edit a string resource

  1. Place caret on a string reference (R.string.key, Res.string.key, @string/key) or a <string> entry in strings.xml.
  2. Ctrl+Alt+E or right-click → Edit String Resource (also Alt+Enter).
  3. Change the key and/or the default and per-locale values. On rename, every reference is updated and the dialog reports how many.

@Preview exclusion

Strings inside @Preview composables are skipped by default (typically dummy data). Toggle in Settings → Tools → StringSmith → Compose Previews.

Shortcuts

Action Shortcut
Extract to strings.xml Ctrl+Alt+X
Quick Extract (skip dialog when unambiguous) Ctrl+Alt+Shift+X
Batch Extract Strings in File Ctrl+Alt+Shift+B
Duplicate String Resource Ctrl+Alt+D
Edit String Resource Ctrl+Alt+E

Compatibility

  • IntelliJ IDEA 2024.2+
  • Android Studio (compatible IntelliJ 242+ platform, i.e. Ladybug 2024.2 and newer)
  • Kotlin plugin K1 and K2 modes
  • Android res/values/ and Compose Multiplatform composeResources/values/ resource layouts

FAQ

Nothing happens when I run Extract / the action is greyed out. The caret must be inside a hardcoded string literal (Kotlin) or an XML attribute value. It won't trigger on an already-extracted reference such as R.string.key. For Duplicate/Edit, place the caret on a string reference or a <string> entry instead.

Extract can't find strings.xml / writes to the wrong module. The target is the resource folder of the module owning the file. Multi-module projects pick the module in the dialog. Make sure the module has a res/values/strings.xml (Android) or composeResources/values/ (CMP) source set.

Compose Multiplatform: it generates R.string instead of Res.string. CMP references are produced only for files under a composeResources/values/ layout. If the generated Res package is mis-detected, set an override under Settings → Tools → StringSmith → Kotlin Multiplatform.

Edit reports "0 references updated". The key is referenced only dynamically (e.g. built by string concatenation or resource-name lookup), which can't be resolved statically. The rename and value edits still apply — only the auto-update of references is skipped.

Strings inside a custom Composable wrapper get getString instead of stringResource. Add the wrapper's name under Settings → Tools → StringSmith → Custom Composable Wrappers so StringSmith treats its trailing lambda as a @Composable scope.

My @Preview strings aren't extracted. That's intentional — @Preview composables are skipped by default (usually dummy data). Toggle it under Settings → Tools → StringSmith → Compose Previews.

Development

./gradlew runIde            # launch sandbox IDE
./gradlew verifyPlugin      # plugin verifier against recommended IDEs
./gradlew buildPlugin       # produce distributable zip
./gradlew test              # run the test suite

License

Apache License 2.0 — see LICENSE.

About

StringSmith - Android Strings Toolkit

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors