Swift Package Index




  • 2.1.0, 3.0.0-beta.9, and master
  • 2.1.0, 3.0.0-beta.9, and master

NStack 🛠

Swift Version Vapor Version CircleCI codebeat badge codecov Readme Score GitHub license

This package is a wrapper around the NStack.io API.

Supports the following NStack modules:

  • Translate

📦 Installation


Add NStack to the Package dependencies:

dependencies: [
    // ...,
    .package(url: "https://github.com/nodes-vapor/nstack.git", from: "3.0.0")

as well as to your target (e.g. "App"):

targets: [
    .target(name: "App", dependencies: [..., "NStack", ...]),
    // ...

Getting started 🚀

Import NStack where needed:

import NStack


Create NStack.Config to configure NStack, your Applications as well as the default Translate.Config.

let nstackConfig = NStack.Config(
    applicationConfigs: [
            name: "my app name",
            applicationId: "NEVER_PUT_API_IDS_IN_SOURCE_CODE",
            restKey: "NEVER_PUT_API_KEYS_IN_SOURCE_CODE"
    defaultTranslateConfig: TranslateController.Config(
        defaultPlatform: .backend,
        defaultLanguage: "en-EN",
        cacheInMinutes: 1
    log: false

If you set log to true you will receive helpful logs in case anything goes wrong.

Adding the Service

Instantiate and register NStackProvider with config created in the previous step. If you plan on using the leaf tag (see below), make sure to use a synchronous cache, such as MemoryKeyedCache (and not RedisCache); otherwise it might break your leaf templates, see https://github.com/vapor/leaf/issues/134

In configure.swift:

// MARK: NStack
try services.register(
        config: nstackConfig,
        cacheFactory: { container in try container.make(MemoryKeyedCache.self) }




func getProductName(req: Request) throws -> Future<String> {

    // ...

    let nstack = try req.make(NStack.self)
    let translation = nstack.application.translate.get(on: req, section: "products", key: "nstackForSale")

    return translation

You can also provide searchReplacePairs:

func getProductName(req: Request, owner: String) throws -> Future<String> {

    let nstack = try req.make(NStack.self)
    let translation = nstack.application.translate.get(
        on: req,
        section: "products",
        key: "nstackForSale",
        searchReplacePairs: [
            "productOwner" : owner

    return translation

If you are using multiple NStack applications within your project you can switch them with getApplication():

let nstack = try req.make(NStack.self)
let translation = nstack.getApplication("my app name").translate.get(on: req, section: "products", key: "nstackForSale")

Note: you can specify the get() call further in case you don't want to go with the values provided in defaultTranslateConfig:

let translation = nstack.application.translate.get(
    on: req,
    platform: .backend,
    language: "dk-DK",
    section: "products",
    key: "nstackForSale",
    searchReplacePairs: [
        "productOwner" : "Christian"
Leaf Tag

In order to render the NStack Leaf tags, you will need to add them first:

public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
    services.register { container -> LeafTagConfig in
        var tags = LeafTagConfig.default()
        try tags.useNStackLeafTags(container)
        return tags

NStack comes with a built-in Leaf tag. The tag yields a translated string or the given key if translation fails

// Get translation for camelCasedSection.camelCasedKey
#nstack:translate("camelCasedSection", "camelCasedKey")

// Get translation for camelCasedSection.camelCasedKey and replace searchString1 with replaceString1 etc
#nstack:translate("camelCasedSection", "camelCasedKey", "searchString1", "replaceString1", "searchString2", "replaceString2", ...)

IMPORTANT: Due to a bug in leaf you have to make sure that the translations are already loaded and available synchronously when rendering the view. This can be achieved by using the NStackPreloadMiddleware on the routes for your views:

let nstackPreloadMiddleware = try container.make(NStackPreloadMiddleware.self)
let unprotectedBackend = router.grouped(nstackPreloadMiddleware)

Please note that the leaf tag always uses the current application with the default translate config that you have provided.

Version Updates

NStack has the ability to retrieve the latest version for a certain platform. You can achieve that with the getLatestVersion(for platform: Platforms) -> Future<UpdateVersion?> method, e.g.:

let nstack = try NStack.makeService(for: req)
nstack.application.version.getLatestVersion(for: .android)


NStack can be used to store JSON responses. To make use of this feature you can use the ResponseController.

let nstack = try NStack.makeService(for: req)
nstack.application.response[42].do { (response: Response) in

This gets the unmodified NStack Response with your JSON data in an object keyed by data, eg.:

{"data":{"myJSONData":"Starts here"}}

Alternatively you can decode your JSON object like so:

nstack.application.response[42].do { (response: [String: String]) in

This would yield your Decodable object, in this case our dictionary: ["myJSONData": "Starts here"].


NStack uses the KeyedCache registered with Vapor. If you don't register any Cache, this should be the KeyedMemory Cache. If you configure Vapor to prefer another Cache, NStack will use this one instead. Example for Redis:

In configure.swift:

config.prefer(DatabaseKeyedCache<ConfiguredDatabase<RedisDatabase>>.self, for: KeyedCache.self)

🏆 Credits

This package is developed and maintained by the Vapor team at Nodes.

📄 License

This package is open-sourced software licensed under the MIT license