Skip to content
Prev Previous commit
Next Next commit
Add locale support to Asset and AssetLibrary classes
- Introduced `language` field in Asset and AssetModel to store locale information.
- Added `setLocale` and `getLocale` methods in Asset and AssetLibrary for locale management.
- Updated tests to verify locale functionality in Asset, AssetLibrary, and AssetModel.
  • Loading branch information
reeshika-h committed Feb 18, 2026
commit 8730d8ee123da3006c1e5106eba80820b297129e
34 changes: 34 additions & 0 deletions src/main/java/com/contentstack/sdk/Asset.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class Asset {
protected String fileSize = null;
protected String fileName = null;
protected String uploadUrl = null;
protected String language = null;
protected JSONObject json = null;
protected String[] tagsArray = null;
protected LinkedHashMap<String, Object> headers;
Expand Down Expand Up @@ -75,6 +76,7 @@ public Asset configure(JSONObject jsonObject) {
this.contentType = model.contentType;
this.fileSize = model.fileSize;
this.uploadUrl = model.uploadUrl;
this.language = model.language;
this.fileName = model.fileName;
this.json = model.json;
this.assetUid = model.uploadedUid;
Expand Down Expand Up @@ -558,6 +560,38 @@ public Asset assetFields(String... fields) {
return this;
}

/**
* Specifies the fields to be included in the asset response.
* <p>
* This method allows you to specify one or more field names, and only those fields
* will be included in the returned asset data. This is useful for reducing response size
* and fetching only the required asset properties.
*
* @param fields Variable number of field names to be included in the asset response.
* @return The {@link Asset} instance for chaining further calls.
*
* <b>Example:</b><br>
* <pre class="prettyprint">
* Asset asset = stack.asset("asset_uid");
* asset.assetFields("title", "filename");
* </pre>
*/

public Asset setLocale(String locale) {
urlQueries.put("locale",locale);
return this;
}


/**
* Returns the locale (language) associated with this asset.
*
* @return The asset's locale as a {@link String}, or {@code null} if not set.
*/
public String getLocale() {
return this.language;
}

/**
* Fetch.
*
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/contentstack/sdk/AssetLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,28 @@ public AssetLibrary includeMetadata() {
return this;
}

/**
* Sets the locale for asset queries.
* <p>
* This method allows you to specify a locale code, so asset results are returned
* for a particular language or region. If not explicitly set, the default locale
* configured in the stack will be used.
*
* @param locale The locale code to filter assets by (e.g., "en-us").
* @return The {@link AssetLibrary} instance for method chaining.
*
* <b>Example:</b>
* <pre class="prettyprint">
* Stack stack = Contentstack.stack("apiKey", "deliveryToken", "environment");
* AssetLibrary assetLibrary = stack.assetLibrary();
* assetLibrary.setLocale("en-us");
* </pre>
*/
public AssetLibrary setLocale(String locale) {
urlQueries.put("locale",locale);
return this;
}

/**
* Gets count.
*
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/contentstack/sdk/AssetModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AssetModel {
String fileSize;
String fileName;
String uploadUrl;
String language;
String[] tags;
JSONObject json;
int count = 0;
Expand All @@ -45,6 +46,7 @@ public AssetModel(JSONObject response, boolean isArray) {
fileSize = (String) json.opt("file_size");
fileName = (String) json.opt("filename");
uploadUrl = (String) json.opt("url");
language = (String) json.opt("locale");
if (json.opt("tags") instanceof JSONArray) {
extractTags();
}
Expand Down
73 changes: 73 additions & 0 deletions src/test/java/com/contentstack/sdk/TestAsset.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,79 @@ void testConfigureWithMinimalJson() {
assertSame(asset, result);
}

@Test
void testConfigureWithLocaleSetsLanguage() {
JSONObject json = new JSONObject();
json.put("uid", "locale_asset_uid");
json.put("locale", "en-us");
json.put("filename", "localized.jpg");

asset.configure(json);
assertEquals("en-us", asset.getLocale());
assertEquals("en-us", asset.language);
}

@Test
void testConfigureWithoutLocaleLeavesLanguageNull() {
JSONObject json = new JSONObject();
json.put("uid", "no_locale_uid");
json.put("filename", "test.jpg");

asset.configure(json);
assertNull(asset.getLocale());
assertNull(asset.language);
}

// ========== LOCALE TESTS (setLocale / getLocale) ==========

@Test
void testSetLocale() {
Asset result = asset.setLocale("en-us");
assertSame(asset, result);
assertTrue(asset.urlQueries.has("locale"));
assertEquals("en-us", asset.urlQueries.get("locale"));
}

@Test
void testSetLocaleReturnsThisForChaining() {
Asset result = asset.setLocale("fr-fr").includeDimension().includeMetadata();
assertSame(asset, result);
assertEquals("fr-fr", asset.urlQueries.get("locale"));
assertTrue(asset.urlQueries.has("include_dimension"));
assertTrue(asset.urlQueries.has("include_metadata"));
}

@Test
void testSetLocaleOverwritesPrevious() {
asset.setLocale("en-us");
assertEquals("en-us", asset.urlQueries.get("locale"));
asset.setLocale("de-de");
assertEquals("de-de", asset.urlQueries.get("locale"));
}

@Test
void testGetLocaleBeforeConfigureReturnsNull() {
assertNull(asset.getLocale());
}

@Test
void testGetLocaleAfterConfigureWithLocale() {
JSONObject json = new JSONObject();
json.put("uid", "uid");
json.put("locale", "ja-jp");
asset.configure(json);
assertEquals("ja-jp", asset.getLocale());
}

@Test
void testGetLocaleAfterSetLocaleOnlySetsQueryNotLanguage() {
asset.setLocale("es-es");
// setLocale only puts in urlQueries; it does not set this.language
assertTrue(asset.urlQueries.has("locale"));
assertEquals("es-es", asset.urlQueries.get("locale"));
assertNull(asset.getLocale()); // getLocale returns this.language, not urlQueries
}

// ========== HEADER TESTS ==========

@Test
Expand Down
35 changes: 35 additions & 0 deletions src/test/java/com/contentstack/sdk/TestAssetLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,41 @@ void testIncludeMetadata() {
assertEquals(true, assetLibrary.urlQueries.get("include_metadata"));
}

// ========== LOCALE TESTS (setLocale for asset localisation) ==========

@Test
void testSetLocale() {
AssetLibrary result = assetLibrary.setLocale("en-us");
assertSame(assetLibrary, result);
assertTrue(assetLibrary.urlQueries.has("locale"));
assertEquals("en-us", assetLibrary.urlQueries.get("locale"));
}

@Test
void testSetLocaleReturnsThisForChaining() {
AssetLibrary result = assetLibrary.setLocale("fr-fr").includeCount().limit(10);
assertSame(assetLibrary, result);
assertEquals("fr-fr", assetLibrary.urlQueries.get("locale"));
assertTrue(assetLibrary.urlQueries.has("include_count"));
assertEquals(10, assetLibrary.urlQueries.get("limit"));
}

@Test
void testSetLocaleOverwritesPrevious() {
assetLibrary.setLocale("en-us");
assertEquals("en-us", assetLibrary.urlQueries.get("locale"));
assetLibrary.setLocale("de-de");
assertEquals("de-de", assetLibrary.urlQueries.get("locale"));
}

@Test
void testSetLocaleWithVariousLocaleCodes() {
assetLibrary.setLocale("ja-jp");
assertEquals("ja-jp", assetLibrary.urlQueries.get("locale"));
assetLibrary.setLocale("pt-br");
assertEquals("pt-br", assetLibrary.urlQueries.get("locale"));
}

// ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ==========

@Test
Expand Down
64 changes: 64 additions & 0 deletions src/test/java/com/contentstack/sdk/TestAssetModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,70 @@ void testConstructorWithAllFields() {
assertEquals(2, model.tags.length);
}

// ========== LOCALE / LANGUAGE TESTS (asset localisation) ==========

@Test
void testConstructorWithLocaleIsArrayTrue() {
JSONObject response = new JSONObject();
response.put("uid", "localized_asset");
response.put("filename", "localized.jpg");
response.put("locale", "en-us");

AssetModel model = new AssetModel(response, true);

assertNotNull(model);
assertEquals("localized_asset", model.uploadedUid);
assertEquals("en-us", model.language);
}

@Test
void testConstructorWithoutLocaleLeavesLanguageNull() {
JSONObject response = new JSONObject();
response.put("uid", "no_locale_asset");
response.put("filename", "test.jpg");

AssetModel model = new AssetModel(response, true);

assertNotNull(model);
assertNull(model.language);
}

@Test
void testConstructorWithVariousLocaleCodes() {
JSONObject response = new JSONObject();
response.put("uid", "uid");
response.put("locale", "fr-fr");

AssetModel model = new AssetModel(response, true);
assertEquals("fr-fr", model.language);

JSONObject response2 = new JSONObject();
response2.put("uid", "uid2");
response2.put("locale", "ja-jp");
AssetModel model2 = new AssetModel(response2, true);
assertEquals("ja-jp", model2.language);
}

@Test
void testConstructorWithLocaleAndOtherFields() {
JSONObject response = new JSONObject();
response.put("uid", "full_localized");
response.put("content_type", "image/png");
response.put("file_size", "1024");
response.put("filename", "image.png");
response.put("url", "https://cdn.example.com/image.png");
response.put("locale", "de-de");

AssetModel model = new AssetModel(response, true);

assertEquals("full_localized", model.uploadedUid);
assertEquals("image/png", model.contentType);
assertEquals("1024", model.fileSize);
assertEquals("image.png", model.fileName);
assertEquals("https://cdn.example.com/image.png", model.uploadUrl);
assertEquals("de-de", model.language);
}

@Test
void testConstructorWithMinimalData() {
JSONObject response = new JSONObject();
Expand Down
Loading