Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Akeneo Product Translation Laravel Package

piotrmus/akeneo-product-translation

A PHP package for handling Akeneo product translations. It helps manage localized product attributes and multilingual catalog values, making it easier to keep Akeneo PIM data consistent across languages. Useful for developers integrating Akeneo translation data into PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and configure. Add the package via Composer (piotrmus/akeneo-product-translation), then check whether it publishes a config file with php artisan vendor:publish --tag=config. You will need Akeneo API credentials to do anything useful: the host URL of your PIM, a client ID and secret (from an Akeneo API connection), plus the username/password of the integration user. Put these in config/akeneo.php — not .env directly — so the package config stays the single source of truth. Akeneo Cloud typically exposes two hosts: one for the API (https://<tenant>.cloud.akeneo.com/api/) and one for the PIM UI. Use the API one; hitting the UI host produces opaque 404s that look like auth errors.

Where to look first, in order:

  1. The service provider. Confirm what the package binds into the container (an AkeneoClient wrapper, a repository, a translator service). This tells you whether you inject a single façade or several granular services. Auto-discovery means you don't register it manually, but read the register()/boot() methods anyway — config keys and bindings live there.
  2. The published config. Look for the channel, locale, and attribute-type defaults. Whether the package ships sensible defaults for localizable and scopable attributes determines how much mapping work you'll be doing.
  3. The core translation service. Read one method end-to-end — typically updateProductTranslation or similar. The shape of the payload (flat attribute-code keyed map vs nested) dictates how you'll build your own callers.

First use case. Pick a single test product with a known SKU and a clearly localizable attribute like name or description. Fetch it via the package, update one locale (en_US → fr_FR), and read it back. Do this in tinker, not in code yet. That single loop — fetch → update → re-fetch — confirms credentials, channel/locale wiring, and payload shape. Everything else is scale.

Implementation Patterns

Inject the service, don't app()->make(). The package advertises Laravel-friendly service binding; use constructor injection so your tests can swap the binding with a fake. Build a thin repository/adaptor class in your app that wraps the package, so the rest of your code doesn't import package namespaces directly. That adaptor is also your migration seam if you outgrow this package (which, at 6 stars and no release since 2022, is a real possibility).

Model the push/pull distinction explicitly. Two workflows dominate:

  • Pull (Akeneo → app): scheduled read of product attributes per channel/locale, write into a local cache or translation table. Use this primarily for review workflows, exports, or rendering a localized product page.
  • Push (app → Akeneo): batch update of localized attribute values from a TMS, translation queue, or internal admin UI. Guard this aggressively — every push is a PATCH against Akeneo and the error surface is large.

Name your service methods after these directions (pushTranslation, pullTranslation) rather than after HTTP verbs. It makes the sync boundary obvious in code review.

Batch, queue, and chunk bulk work. The description advertises bulk workflows, but "bulk" against Akeneo means the API's own batch endpoint (typically limited to ~{n} products per request) and rate-limited integrations. Wrap every bulk operation in a queued job per chunk, not one big synchronous call. Retry on 429 and 5xx with exponential backoff; do not retry 4xx auth or validation errors, they will fail identically. Log the SKU list per chunk so a failed chunk can be re-driven.

Scope every call by channel and locale. Akeneo distinguishes localizable (locale-aware), scopable (channel-aware), and attributes that are both or neither. A PATCH that omits the locale/scope for a localizable attribute will either be rejected or silently write to the wrong scope. Build a small mapping object — (attribute_code, channel, locale, value) — and pass it around rather than naked arrays. That object is also your natural test fixture.

Keep translation state in your own schema. Do not use Akeneo as the source of truth for "which translations are pending" or "who signed off." Store translation rows locally (product code, attribute, channel, locale, value, workflow_state, updated_at), push to Akeneo on commit, and reconcile occasionally. Otherwise your workflow logic lives in Akeneo attribute options, which is painful to query and impossible to roll back.

Integration tips. If you have an existing TMS or translation queue, hook the package in at the attribute-level boundary, not the product-level one. Product-level pushes re-translate data that hasn't changed, waste Akeneo API quota, and produce noisier audit logs. Attribute-level updates are idempotent and much easier to test.

Gotchas and Tips

The changelog doesn't match the package. The v0.2.2 release note says "Fix ACL resource code" — that is almost certainly metadata from a different package or a monorepo changelog. There is no ACL layer in a product-translation package. Treat the release history as unreliable and read source when you need to know what changed. This is a real signal about maintainer hygiene, not a nit.

Low adoption, stale release. Six stars and no release since September 2022 means: no community answers on Stack Overflow, no guarantee that Akeneo's current API (v5/v6/v7) is compatible, and probably no active maintenance. Pin the exact version in composer.json ("0.2.2", not ^0.2). Before committing, spike one read and one write against a real Akeneo instance — API drift is the most likely reason this package fails to install cleanly.

Rate limiting is the day-to-day bottleneck. Akeneo enforces integration-level limits (historically around 10 requests/second, but verify for your tier). Do not loop single-product calls on a list endpoint; use the batch endpoints the package exposes, and add a token-bucket or usleep inside your job handler. A 429 that succeeds on retry is a symptom, not a solution — the retries are eating your queue workers.

Locale and scope mismatches fail silently or confusingly. Akeneo will accept a PATCH with a locale that isn't activated on the channel in some configurations, and reject it in others. Before writing any push code, list the channels and locales on the PIM (/api/v1/channels, /api/v1/locales) and validate inputs against that list in your app. The package won't do this for you, and an invalid locale looks identical to an invalid attribute code in error responses.

Attribute types are not interchangeable. Akeneo has ~15 attribute types (text, textarea, pim_catalog_metric, pim_catalog_simpleselect, etc.) and each has different payload requirements. A metric needs a unit, a simpleselect needs an option code, a pim_catalog_image needs a binary/media reference — not a URL string. The package likely treats them uniformly as "value", which means you must validate and coerce. Build a small per-type normalizer; it will save you hours of 422 Unprocessable Entity debugging.

Credentials and auth flow. Akeneo's OAuth password grant requires client_id, secret, username, password — four values, all correct, and the integration user must be granted API permissions in the PIM. A user that can log into the UI but has not been added to the API connection gets a 401. Rotate secrets via env, never commit them, and set a short token TTL cache on your side — the package may re-authenticate on every request, which doubles your effective rate limit.

Silent no-ops on attribute-level writes. A push that succeeds with HTTP 200 can still write nothing if the attribute is not enabled for the product's family, or if the channel/locale combination doesn't apply to that attribute. Re-fetch after every push in development to confirm the value stuck. In production, reconcile at a lower cadence — daily — rather than trusting the push response.

Testing against Akeneo is slow. You will not want to hit the real PIM in every test. Wrap whatever client the package binds behind your own interface and fake it at that seam. Keep a small set of opt-in integration tests (tagged @integration, run manually or nightly) against a staging PIM with a dedicated test product family — those are the only tests that catch real payload-shape bugs.

Extension points worth knowing. The three seams you are most likely to need are: the HTTP client binding (for retries, logging, metrics), the payload builder/normalizer (for handling attribute types you care about), and the config array (for channel/locale defaults). Everything else in a package this size is usually better replaced with your own code than fought with — the integration surface is small, and you will almost certainly need to extend the payload normalizer within the first month.

Budget for replacement. Given the maintenance profile, structure your code so the package sits behind an adaptor interface you own. When Akeneo's API version moves on, or an attribute type arrives the package can't handle, you swap the adaptor's implementation for a handful of direct Saloon/Guzzle calls and keep the rest of your application untouched. That is the difference between buying six months and buying a rewrite.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource