Skip to content

Commit

Permalink
Merge pull request #14 from icerockdev/develop
Browse files Browse the repository at this point in the history
release 0.5.0
  • Loading branch information
Alex009 authored Nov 19, 2019
2 parents 327eef8 + bffb474 commit d918d2f
Show file tree
Hide file tree
Showing 16 changed files with 141 additions and 141 deletions.
20 changes: 6 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
![moko-resources](img/logo.png)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) [![Download](https://api.bintray.com/packages/icerockdev/moko/moko-resources/images/download.svg) ](https://bintray.com/icerockdev/moko/moko-resources/_latestVersion) ![kotlin-version](https://img.shields.io/badge/kotlin-1.3.50-orange)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) [![Download](https://api.bintray.com/packages/icerockdev/moko/moko-resources/images/download.svg) ](https://bintray.com/icerockdev/moko/moko-resources/_latestVersion) ![kotlin-version](https://img.shields.io/badge/kotlin-1.3.60-orange)

# Mobile Kotlin resources
This is a Kotlin MultiPlatform library that provides access to the resources on iOS & Android with the support of the default system localization.
Expand All @@ -21,7 +21,7 @@ This is a Kotlin MultiPlatform library that provides access to the resources on

## Requirements
- Gradle version 5.4.1+
- Android API 21+
- Android API 16+
- iOS version 9.0+

## Versions
Expand All @@ -30,6 +30,8 @@ This is a Kotlin MultiPlatform library that provides access to the resources on
- 0.2.0
- 0.3.0
- 0.4.0
- kotlin 1.3.60
- 0.5.0

## Installation
root build.gradle
Expand All @@ -40,7 +42,7 @@ buildscript {
}
dependencies {
classpath "dev.icerock.moko:resources-generator:0.4.0"
classpath "dev.icerock.moko:resources-generator:0.5.0"
}
}
Expand All @@ -57,7 +59,7 @@ project build.gradle
apply plugin: "dev.icerock.mobile.multiplatform-resources"
dependencies {
commonMainApi("dev.icerock.moko:resources:0.4.0")
commonMainApi("dev.icerock.moko:resources:0.5.0")
}
multiplatformResources {
Expand All @@ -70,16 +72,6 @@ settings.gradle
enableFeaturePreview("GRADLE_METADATA")
```

On iOS, in addition to the Kotlin library add Pod in the Podfile.
```ruby
pod 'MultiPlatformLibraryResources', :git => 'https://github.com/icerockdev/moko-resources.git', :tag => 'release/0.4.0'
```
**`MultiPlatformLibraryResources` CocoaPod requires that the framework compiled from Kotlin be named
`MultiPlatformLibrary` and be connected as a CocoaPod `MultiPlatformLibrary`.
[Here](sample/ios-app/Podfile)'s an example.
To simplify integration with MultiPlatformFramework you can use [mobile-multiplatform-plugin](https://github.com/icerockdev/mobile-multiplatform-gradle-plugin)**.
`MultiPlatformLibraryResources` CocoaPod contains an extension `localized` for `StringDesc`.

## Usage
### Example 1 - simple localization string
The first step is a create a file `strings.xml` in `commonMain/resources/MR/base` with the following content:
Expand Down
6 changes: 3 additions & 3 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ repositories {
}

dependencies {
implementation("dev.icerock:mobile-multiplatform:0.3.0")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50")
implementation("com.android.tools.build:gradle:3.5.0")
implementation("dev.icerock:mobile-multiplatform:0.4.0")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.60")
implementation("com.android.tools.build:gradle:3.5.2")
}

kotlinDslPluginOptions {
Expand Down
3 changes: 0 additions & 3 deletions buildSrc/src/main/kotlin/Deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ object Deps {
"com.android.tools.build:gradle:${Versions.Plugins.android}"
const val kotlin =
"org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Plugins.kotlin}"
const val androidExtensions =
"org.jetbrains.kotlin:kotlin-android-extensions:${Versions.Plugins.androidExtensions}"
const val mokoResources =
"dev.icerock.moko:resources-generator:${Versions.Plugins.mokoResources}"
}
Expand Down Expand Up @@ -47,7 +45,6 @@ object Deps {
"org.jetbrains.kotlin.multiplatform" to Plugins.kotlin,
"kotlin-kapt" to Plugins.kotlin,
"kotlin-android" to Plugins.kotlin,
"kotlin-android-extensions" to Plugins.androidExtensions,
"dev.icerock.mobile.multiplatform-resources" to Plugins.mokoResources
)
}
11 changes: 5 additions & 6 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,23 @@ object Versions {
object Android {
const val compileSdk = 28
const val targetSdk = 28
const val minSdk = 21
const val minSdk = 16
}

const val kotlin = "1.3.50"
const val kotlin = "1.3.60"

private const val mokoResources = "0.4.0"
private const val mokoResources = "0.5.0"

object Plugins {
const val android = "3.4.1"
const val android = "3.5.2"

const val kotlin = Versions.kotlin
const val androidExtensions = Versions.kotlin
const val mokoResources = Versions.mokoResources
}

object Libs {
object Android {
const val appCompat = "1.0.2"
const val appCompat = "1.1.0"
}

object MultiPlatform {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ class CommonMRGenerator(

project.tasks
.mapNotNull { it as? KotlinNativeLink }
.forEach { it.dependsOn(generationTask) }
.forEach { it.compilation.compileKotlinTask.dependsOn(generationTask) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class IosMRGenerator(
.filter { it.compilation.kotlinSourceSets.contains(sourceSet) }

linkTasks.forEach { linkTask ->
linkTask.dependsOn(generationTask)
linkTask.compilation.compileKotlinTask.dependsOn(generationTask)

val framework = linkTask.binary as? Framework ?: return@forEach

Expand Down
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ org.gradle.parallel=true
kotlin.code.style=official

android.useAndroidX=true
android.enableJetifier=true
android.databinding.enableV2=true
android.enableJetifier=true
15 changes: 10 additions & 5 deletions resources/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.multiplatform")
id("kotlin-android-extensions")
id("dev.icerock.mobile.multiplatform")
id("maven-publish")
}
Expand All @@ -22,10 +21,6 @@ android {
}
}

androidExtensions {
isExperimental = true
}

dependencies {
mppLibrary(Deps.Libs.MultiPlatform.kotlinStdLib)

Expand All @@ -42,3 +37,13 @@ publishing {
}
}
}

kotlin {
targets.filterIsInstance<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>().forEach { target ->
target.compilations.getByName("main") {
val pluralizedString by cinterops.creating {
defFile(project.file("src/iosMain/def/pluralizedString.def"))
}
}
}
}
10 changes: 10 additions & 0 deletions resources/src/iosMain/def/pluralizedString.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
language = Objective-C
package = dev.icerock.moko.resources.objc
---
#import <Foundation/NSString.h>
#import <Foundation/NSBundle.h>

NSString* pluralizedString(NSBundle* bundle, NSString* resourceId, int number) {
NSString* localized = [bundle localizedStringForKey: resourceId value: nil table: nil];
return [NSString localizedStringWithFormat:localized, number];
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ package dev.icerock.moko.resources.desc

import dev.icerock.moko.resources.PluralsResource
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.objc.pluralizedString
import platform.Foundation.NSString
import platform.Foundation.stringWithFormat

actual sealed class StringDesc {
actual data class Resource actual constructor(val stringRes: StringResource) : StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {
override fun localized(): String {
return stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null)
}
}
Expand All @@ -18,21 +21,26 @@ actual sealed class StringDesc {
val stringRes: StringResource,
val args: List<Any>
) : StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {
val string = stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null)
return formatter.formatString(string, args.toTypedArray())
}

actual constructor(stringRes: StringResource, vararg args: Any) : this(
stringRes,
args.toList()
)

override fun localized(): String {
val string = stringRes.bundle.localizedStringForKey(stringRes.resourceId, null, null)
return stringWithFormat(string, args.toTypedArray())
}
}

actual data class Plural actual constructor(val pluralsRes: PluralsResource, val number: Int) :
StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {
return formatter.plural(pluralsRes, number)

override fun localized(): String {
return pluralizedString(
bundle = pluralsRes.bundle,
resourceId = pluralsRes.resourceId,
number = number
)!!
}
}

Expand All @@ -41,41 +49,96 @@ actual sealed class StringDesc {
val number: Int,
val args: List<Any>
) : StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {
return formatter.formatPlural(pluralsRes, number, args.toTypedArray())
}

actual constructor(pluralsRes: PluralsResource, number: Int, vararg args: Any) : this(
pluralsRes,
number,
args.toList()
)

override fun localized(): String {
val pluralized = pluralizedString(
bundle = pluralsRes.bundle,
resourceId = pluralsRes.resourceId,
number = number
)!!
return stringWithFormat(pluralized, args.toTypedArray())
}
}

actual data class Raw actual constructor(val string: String) : StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {

override fun localized(): String {
return string
}
}

actual data class Composition actual constructor(val args: List<StringDesc>, val separator: String?) : StringDesc() {
override fun toLocalizedString(formatter: Formatter): String {
return StringBuilder().apply {
args.forEachIndexed { index, stringDesc ->
if(index != 0 && separator != null) {
append(separator)
}
append(stringDesc.toLocalizedString(formatter))
}
}.toString()
actual data class Composition actual constructor(
val args: List<StringDesc>,
val separator: String?
) : StringDesc() {
override fun localized(): String {
return args.joinToString(separator = separator ?: "") { it.localized() }
}
}

abstract fun toLocalizedString(formatter: Formatter): String
abstract fun localized(): String

interface Formatter {
fun formatString(string: String, args: Array<out Any>): String
fun plural(resource: PluralsResource, number: Int): String
fun formatPlural(resource: PluralsResource, number: Int, args: Array<out Any>): String
protected fun stringWithFormat(format: String, args: Array<out Any>): String {
// NSString format works with NSObjects via %@, we should change standard format to %@
val objcFormat = format.replace(Regex("%[\\.|\\d]*[a|b|c|d|e|f|s]"), "%@")
// bad but objc interop limited :(
// When calling variadic C functions spread operator is supported only for *arrayOf(...)
return when (args.size) {
0 -> NSString.stringWithFormat(objcFormat)
1 -> NSString.stringWithFormat(objcFormat, args[0])
2 -> NSString.stringWithFormat(objcFormat, args[0], args[1])
3 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2])
4 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2], args[3])
5 -> NSString.stringWithFormat(objcFormat, args[0], args[1], args[2], args[3], args[4])
6 -> NSString.stringWithFormat(
objcFormat,
args[0],
args[1],
args[2],
args[3],
args[4],
args[5]
)
7 -> NSString.stringWithFormat(
objcFormat,
args[0],
args[1],
args[2],
args[3],
args[4],
args[5],
args[6]
)
8 -> NSString.stringWithFormat(
objcFormat,
args[0],
args[1],
args[2],
args[3],
args[4],
args[5],
args[6],
args[7]
)
9 -> NSString.stringWithFormat(
objcFormat,
args[0],
args[1],
args[2],
args[3],
args[4],
args[5],
args[6],
args[7],
args[8]
)
else -> throw IllegalArgumentException("can't handle more then 9 arguments now")
}
}
}
Loading

0 comments on commit d918d2f

Please sign in to comment.